Skip to content

Instantly share code, notes, and snippets.

@lnlonSA
Created December 26, 2016 18:56
Show Gist options
  • Save lnlonSA/d8933a2c57a417ec1b3e56b573117a7d to your computer and use it in GitHub Desktop.
Save lnlonSA/d8933a2c57a417ec1b3e56b573117a7d to your computer and use it in GitHub Desktop.
مشروع أمن نظم المعلومات
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package bitcion;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import javax.crypto.*;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import sun.misc.*;
/**
*
* @author LaNa Sa
*/
public class AES {
private static final byte[] key = "MyDifficultPassw".getBytes();
private static final String transformation = "AES/ECB/PKCS5Padding";
public static SealedObject encrypt(Serializable object,byte[] key) throws IOException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException {
try {
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
MessageDigest digest = MessageDigest.getInstance("SHA-256");
final byte[] reallyHashed = digest.digest(key);
SecretKeySpec sks = new SecretKeySpec(reallyHashed, "AES");
cipher.init(Cipher.ENCRYPT_MODE, sks);
SealedObject sealedObject = new SealedObject(object, cipher);
return sealedObject;
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
return null;
}
}
public static Object decrypt(SealedObject enc_data,byte[] key) throws IOException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException {
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
MessageDigest digest = MessageDigest.getInstance("SHA-256");
final byte[] reallyHashed = digest.digest(key);
SecretKeySpec sks = new SecretKeySpec(reallyHashed, "AES");
cipher.init(Cipher.DECRYPT_MODE, sks);
try {
return enc_data.getObject(cipher);
} catch (ClassNotFoundException | IllegalBlockSizeException | BadPaddingException e) {
e.printStackTrace();
return null;
}
}
}
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package bitcion;
import java.security.Key;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
/**
*
* @author LaNa Sa
*/
public class AESstringEncrypt {
private static final String ALGO = "AES";
public static String encrypt(String Data,byte[] passPhrase) throws Exception {
Key key = generateKey(passPhrase);
Cipher c = Cipher.getInstance(ALGO);
c.init(Cipher.ENCRYPT_MODE, key);
byte[] encVal = c.doFinal(Data.getBytes());
String encryptedValue = new BASE64Encoder().encode(encVal);
return encryptedValue;
}
public static String decrypt(String encryptedData,byte[] passPhrase) throws Exception {
Key key = generateKey(passPhrase);
Cipher c = Cipher.getInstance(ALGO);
c.init(Cipher.DECRYPT_MODE, key);
byte[] decordedValue = new BASE64Decoder().decodeBuffer(encryptedData);
byte[] decValue = c.doFinal(decordedValue);
String decryptedValue = new String(decValue);
return decryptedValue;
}
private static Key generateKey(byte[] passPhrase) throws Exception {
Key key = new SecretKeySpec(passPhrase, ALGO);
return key;
}
}
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package bitcion;
import static bitcion.ClientClass.readKeyPair;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.PrintWriter;
import java.io.Writer;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
/**
*
* @author LaNa Sa
*/
public class CertificateAuthority extends Thread{
private ServerSocket mySocket;
private KeyPair myPair;
private byte[] passPhrase = new byte[] { 'T', 'h', 'e', 'B', 'e', 's', 't',
'S', 'e', 'c', 'r','e', 't', 'K', 'e', 'y' };
private int cerSerialNumber;
private String CAname;
private Map<String,CertificateRequest> requests;
private Map<String,DigitalCertificate> certificates;
public CertificateAuthority(int port,String CAname) throws IOException {
mySocket = new ServerSocket(port);
this.CAname = CAname;
requests = new HashMap<>();
certificates = new HashMap<>();
// Get my KeyPair from file:
myPair = readKeyPair();
}
public KeyPair readKeyPair() throws FileNotFoundException
{
BufferedReader br;
try {
br = new BufferedReader(new FileReader("CAPublicKey.txt"));
StringBuilder sb = new StringBuilder();
String line = br.readLine();
while (line != null) {
sb.append(line);
sb.append(System.lineSeparator());
line = br.readLine();
}
String publicK = sb.toString();
//convert public key from String to PublicKey:
byte[] publicBytes = new BASE64Decoder().decodeBuffer(publicK);
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey pubKey = keyFactory.generatePublic(keySpec);
br.close();
br = new BufferedReader(new FileReader("CAPrivateKey.txt"));
sb = new StringBuilder();
line = br.readLine();
while (line != null) {
sb.append(line);
sb.append(System.lineSeparator());
line = br.readLine();
}
String EncPrivateK = sb.toString();
//decrypte privatekey:
String privateK = AESstringEncrypt.decrypt(EncPrivateK,passPhrase);
//convert private key from String to PrivateKey:
byte[] privateBytes = new BASE64Decoder().decodeBuffer(privateK);
PKCS8EncodedKeySpec keySpec2 = new PKCS8EncodedKeySpec(privateBytes);
PrivateKey privKey = keyFactory.generatePrivate(keySpec2);
br.close();
//genrate keyPair:
return new KeyPair(pubKey, privKey);
} catch (IOException ex) {
Logger.getLogger(ClientClass.class.getName()).log(Level.SEVERE, null, ex);
return null;
} catch (NoSuchAlgorithmException ex) {
Logger.getLogger(ClientClass.class.getName()).log(Level.SEVERE, null, ex);
return null;
} catch (InvalidKeySpecException ex) {
Logger.getLogger(ClientClass.class.getName()).log(Level.SEVERE, null, ex);
return null;
} catch (Exception ex) {
Logger.getLogger(CertificateAuthority.class.getName()).log(Level.SEVERE, null, ex);
return null;
}
}
public void generateAndStoreKeys()
{
try{
//generate keypair for CA:
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
keyPairGen.initialize(2048);
KeyPair keyPair = keyPairGen.genKeyPair();
PublicKey publicKey = keyPair.getPublic();
PrivateKey privateKey = keyPair.getPrivate();
//convert keys to string fpr store them:
String publicK = new BASE64Encoder().encode(publicKey.getEncoded());
String privateK = new BASE64Encoder().encode(privateKey.getEncoded());
//encrypt private key with AES:
String encPrivateK = AESstringEncrypt.encrypt(privateK, passPhrase);
//store public key:
PrintWriter writer = new PrintWriter("CAPublicKey.txt");
writer.println(publicK);
writer.close();
//store encrypted privateKey:
writer = new PrintWriter("CAPrivateKey.txt");
writer.println(encPrivateK);
writer.close();
} catch (IOException e) {
// do something
} catch (Exception ex) {
Logger.getLogger(CertificateAuthority.class.getName()).log(Level.SEVERE, null, ex);
}
}
public void run() {
while(true) {
try {
System.out.println("Waiting for client on port " +
mySocket.getLocalPort() + "...");
Socket server = mySocket.accept();
System.out.println("Just connected to " + server.getRemoteSocketAddress());
ObjectInputStream in = new ObjectInputStream(server.getInputStream());
ObjectOutputStream out = new ObjectOutputStream(server.getOutputStream());
String operationName;
//get operation Name:
operationName = (String) in.readObject();
switch(operationName)
{
case "Certificate Request":{
//recive certificate request from client:
CertificateRequest crs = (CertificateRequest) in.readObject();
//add request to requests:
requests.put(crs.getSubjectName(), crs);
break;
}
case "Send Certificate":{
//get the subject Name from client:
String subjectName = (String)in.readObject();
//cheack if certificate is found:
boolean cheack = certificates.containsKey(subjectName);
if(cheack)
{
//send to client that there is certificate.
String msg = "found";
out.writeObject(msg);
out.flush();
DigitalCertificate cer = certificates.get(subjectName);
//send certificate to the client:
out.writeObject(cer);
out.flush();
}else
{
//send to client that there is no certificate.
String msg = "not found";
out.writeObject(msg);
out.flush();
}
}
}
server.close();
//process all requests:
ProcessCertificatesRequests();
System.out.println(certificates.keySet());
}catch(SocketTimeoutException s) {
System.out.println("Socket timed out!");
break;
}catch(IOException e) {
e.printStackTrace();
break;
} catch (Exception ex) {
Logger.getLogger(ServerClass.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
public void ProcessCertificatesRequests()
{
for (CertificateRequest crs : requests.values()) {
//cheack request Validity:
boolean validityCheack = crs.Verify();
cerSerialNumber = certificates.size() + 1;
//if request valid make certificate and store it:
DigitalCertificate cer = DigitalCertificate.createCer(cerSerialNumber,
CAname,
crs.getSubjectName(),
crs.getSubjectPublicKey(),
720,
myPair.getPrivate()
);
certificates.put(crs.getSubjectName(), cer);
}
//clear processed Requests:
requests.clear();
}
public static void main(String[] args) {
try {
CertificateAuthority ca = new CertificateAuthority(1234,"BitCionCA");
ca.start();
} catch (IOException ex) {
Logger.getLogger(CertificateAuthority.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package bitcion;
import java.io.Serializable;
import java.security.PrivateKey;
import java.security.PublicKey;
/**
*
* @author LaNa Sa
*/
public class CertificateRequest implements Serializable{
private String SubjectName;
private PublicKey subjectPublicKey;
private byte[] signature;
public static CertificateRequest create(String subjectName,PublicKey subjectPublicKey,PrivateKey clientPrivateKey)
{
CertificateRequest CRS = new CertificateRequest();
CRS.SubjectName = subjectName;
CRS.subjectPublicKey = subjectPublicKey;
byte[] crsInfo = CRS.concat(CRS.SubjectName.getBytes(),CRS.subjectPublicKey.getEncoded());
CRS.findSignature(crsInfo, clientPrivateKey);
return CRS;
}
private void findSignature(byte[] cer,PrivateKey CAPrivateKey)
{
//concate certificate fildes for find signature:
signature = GenerateSignature.generate(cer, CAPrivateKey);
}
public byte[] concat(byte[]...arrays)
{
// Determine the length of the result array
int totalLength = 0;
for (int i = 0; i < arrays.length; i++)
{
totalLength += arrays[i].length;
}
// create the result array
byte[] result = new byte[totalLength];
// copy the source arrays into the result array
int currentIndex = 0;
for (int i = 0; i < arrays.length; i++)
{
System.arraycopy(arrays[i], 0, result, currentIndex, arrays[i].length);
currentIndex += arrays[i].length;
}
return result;
}
public String getSubjectName() {
return SubjectName;
}
public PublicKey getSubjectPublicKey() {
return subjectPublicKey;
}
public byte[] getSignature() {
return signature;
}
public boolean Verify()
{
byte[] crsInfo = this.concat(this.SubjectName.getBytes(),this.subjectPublicKey.getEncoded());
return VerficationSignature.verify(crsInfo, signature, this.subjectPublicKey);
}
}
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package bitcion;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SealedObject;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
/**
*
* @author LaNa Sa
*/
public class ClientClass {
public static KeyPair readKeyPair() throws FileNotFoundException
{
BufferedReader br;
try {
br = new BufferedReader(new FileReader("publicKey.txt"));
StringBuilder sb = new StringBuilder();
String line = br.readLine();
while (line != null) {
sb.append(line);
sb.append(System.lineSeparator());
line = br.readLine();
}
String publicK = sb.toString();
//convert public key from String to PublicKey:
byte[] publicBytes = new BASE64Decoder().decodeBuffer(publicK);
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey pubKey = keyFactory.generatePublic(keySpec);
br.close();
br = new BufferedReader(new FileReader("privateKey.txt"));
sb = new StringBuilder();
line = br.readLine();
while (line != null) {
sb.append(line);
sb.append(System.lineSeparator());
line = br.readLine();
}
String privateK = sb.toString();
//convert private key from String to PublicKey:
byte[] privateBytes = new BASE64Decoder().decodeBuffer(privateK);
PKCS8EncodedKeySpec keySpec2 = new PKCS8EncodedKeySpec(privateBytes);
PrivateKey privKey = keyFactory.generatePrivate(keySpec2);
br.close();
//genrate keyPair:
return new KeyPair(pubKey, privKey);
} catch (IOException ex) {
Logger.getLogger(ClientClass.class.getName()).log(Level.SEVERE, null, ex);
return null;
} catch (NoSuchAlgorithmException ex) {
Logger.getLogger(ClientClass.class.getName()).log(Level.SEVERE, null, ex);
return null;
} catch (InvalidKeySpecException ex) {
Logger.getLogger(ClientClass.class.getName()).log(Level.SEVERE, null, ex);
return null;
}
}
public static void generateAndStoreKeys()
{
try{
//generate keypair for CA:
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
keyPairGen.initialize(2048);
KeyPair keyPair = keyPairGen.genKeyPair();
PublicKey publicKey = keyPair.getPublic();
PrivateKey privateKey = keyPair.getPrivate();
//convert keys to string fpr store them:
String publicK = new BASE64Encoder().encode(publicKey.getEncoded());
String privateK = new BASE64Encoder().encode(privateKey.getEncoded());
//store public key:
PrintWriter writer = new PrintWriter("publicKey.txt");
writer.println(publicK);
writer.close();
//store encrypted privateKey:
writer = new PrintWriter("privateKey.txt");
writer.println(privateK);
writer.close();
} catch (IOException e) {
// do something
} catch (Exception ex) {
Logger.getLogger(CertificateAuthority.class.getName()).log(Level.SEVERE, null, ex);
}
}
public static void main(String[] argc) throws FileNotFoundException
{
String server_name="localhost";
int port_number=1234;
KeyPair myPair = null;
// Get my KeyPair from file:
myPair = readKeyPair();
System.out.println("Connecting to "+server_name+" on port "+port_number);
try {
Socket client = new Socket(server_name,port_number);
System.out.println(client.getRemoteSocketAddress());
ObjectOutputStream out = new ObjectOutputStream(client.getOutputStream());
ObjectInputStream in = new ObjectInputStream(client.getInputStream());
//generate certificaterequest:
CertificateRequest crs = CertificateRequest.create("192.168.1.116",myPair.getPublic(), myPair.getPrivate());
//send Request to CA:
out.writeObject(crs);
out.flush();
//recv Certificate from CA:
DigitalCertificate cer = (DigitalCertificate) in.readObject();
//view certificate:
System.out.println(cer.toString());
//finish and close the socket:
client.close();
//open socket with system server:
port_number=6000;
System.out.println("Connecting to "+server_name+" on port "+port_number);
client = new Socket(server_name,port_number);
System.out.println(client.getRemoteSocketAddress());
out = new ObjectOutputStream(client.getOutputStream());
in = new ObjectInputStream(client.getInputStream());
//send signup request to server:
out.writeObject(new String("signUp"));
out.flush();
//send my certificate to server:
out.writeObject(cer);
//finish and close the socket:
client.close();
} catch (IOException ex) {
Logger.getLogger(ClientClass.class.getName()).log(Level.SEVERE, null, ex);
} catch (ClassNotFoundException ex) {
Logger.getLogger(ClientClass.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package bitcion;
import java.io.Serializable;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import sun.misc.BASE64Encoder;
/**
*
* @author LaNa Sa
*/
public class DigitalCertificate implements Serializable{
private int serialNumber;
private String issuerName;
private Date IssuingDate;
private Date validityFinishDate;
private int validity;
private String subjectName;
private PublicKey subjectPublicKey;
private byte[] signature;
public static DigitalCertificate createCer(int serialNumber,String issuerName,String subjectName
,PublicKey subjectPublicKey,int validity,PrivateKey CAPrivateKey)
{
DigitalCertificate cer = new DigitalCertificate();
cer.serialNumber = serialNumber;
cer.issuerName = issuerName;
cer.validity = validity;
cer.findDates();
cer.subjectName = subjectName;
cer.subjectPublicKey = subjectPublicKey;
cer.findSignature(cer.cerToByte(), CAPrivateKey);
return cer;
}
private void findDates()
{
//issuing date is the current date:
IssuingDate = new Date();
//validity finish date is the issuaing date + validity days:
Calendar c= new GregorianCalendar();
c.add(Calendar.DATE, validity);
validityFinishDate = c.getTime();
}
private void findSignature(byte[] cer,PrivateKey CAPrivateKey)
{
//concate certificate fildes for find signature:
signature = GenerateSignature.generate(cer, CAPrivateKey);
}
public byte[] cerToByte()
{
return concat( Integer.toString(serialNumber).getBytes(),
issuerName.getBytes(),
IssuingDate.toString().getBytes(),
validityFinishDate.toString().getBytes(),
subjectName.getBytes(),
subjectPublicKey.getEncoded()
) ;
}
public byte[] concat(byte[]...arrays)
{
// Determine the length of the result array
int totalLength = 0;
for (int i = 0; i < arrays.length; i++)
{
totalLength += arrays[i].length;
}
// create the result array
byte[] result = new byte[totalLength];
// copy the source arrays into the result array
int currentIndex = 0;
for (int i = 0; i < arrays.length; i++)
{
System.arraycopy(arrays[i], 0, result, currentIndex, arrays[i].length);
currentIndex += arrays[i].length;
}
return result;
}
@Override
public String toString() {
//convert keys to string fpr store them:
String publicK = new BASE64Encoder().encode(subjectPublicKey.getEncoded());
return "DigitalCertificate:" + "\nserialNumber=" + serialNumber + "\nissuerName=" + issuerName + "\nIssuingDate=" + IssuingDate + "\nvalidityFinishDate=" + validityFinishDate + "\nvalidity=" + validity + "\nsubjectName=" + subjectName + "\nsubjectPublicKey=" + publicK + "\nsignature=" + signature ;
}
public int getSerialNumber() {
return serialNumber;
}
public String getIssuerName() {
return issuerName;
}
public Date getIssuingDate() {
return IssuingDate;
}
public Date getValidityFinishDate() {
return validityFinishDate;
}
public int getValidity() {
return validity;
}
public String getSubjectName() {
return subjectName;
}
public PublicKey getSubjectPublicKey() {
return subjectPublicKey;
}
public byte[] getSignature() {
return signature;
}
public void setSerialNumber(int serialNumber) {
this.serialNumber = serialNumber;
}
public void setIssuerName(String issuerName) {
this.issuerName = issuerName;
}
public void setIssuingDate(Date IssuingDate) {
this.IssuingDate = IssuingDate;
}
public void setValidityFinishDate(Date validityFinishDate) {
this.validityFinishDate = validityFinishDate;
}
public void setValidity(int validity) {
this.validity = validity;
}
public void setSubjectName(String subjectName) {
this.subjectName = subjectName;
}
public void setSubjectPublicKey(PublicKey subjectPublicKey) {
this.subjectPublicKey = subjectPublicKey;
}
public void setSignature(byte[] signature) {
this.signature = signature;
}
public boolean Verify(PublicKey CAPublicKey){
//test if the CA name is same as the CA of system:
if(!this.issuerName.equals("BitCionCA"))
return false;
//test if CA publicKey is right:
if(!VerficationSignature.verify(this.cerToByte(), this.getSignature(), CAPublicKey))
return false;
//test certificate validity:
Date currentDate = new Date();
if(currentDate.after(this.getValidityFinishDate()))
return false;
return true;
}
}
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package bitcion;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.Signature;
import java.security.SignatureException;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* @author LaNa Sa
*/
public class GenerateSignature {
public static byte[] generate(byte[] message,PrivateKey pk)
{
Signature sig;
try {
sig = Signature.getInstance("MD5WithRSA");
sig.initSign(pk);
sig.update(message);
return sig.sign();
} catch (NoSuchAlgorithmException ex) {
Logger.getLogger(GenerateSignature.class.getName()).log(Level.SEVERE, null, ex);
return null;
} catch (InvalidKeyException ex) {
Logger.getLogger(GenerateSignature.class.getName()).log(Level.SEVERE, null, ex);
return null;
} catch (SignatureException ex) {
Logger.getLogger(GenerateSignature.class.getName()).log(Level.SEVERE, null, ex);
return null;
}
}
}
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package bitcion;
/**
*
* @author LaNa Sa
*/
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.crypto.*;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import sun.misc.*;
public class RSA {
public static SealedObject encrypt(Serializable message,Key kp) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IOException, IllegalBlockSizeException
{
// Get an instance of the Cipher for RSA encryption/decryption
Cipher c = Cipher.getInstance("RSA");
// Initiate the Cipher, telling it that it is going to Encrypt, giving it the public key
c.init(Cipher.ENCRYPT_MODE,kp);
// Encrypt that message using a new SealedObject and the Cipher we created before
SealedObject EncryptedMessage= new SealedObject( message, c);
return EncryptedMessage;
}
public static Object decrypt(SealedObject EncryptedMessage,Key kp) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IOException, ClassNotFoundException, IllegalBlockSizeException, BadPaddingException
{
// Get an instance of the Cipher for RSA encryption/decryption
Cipher dec = Cipher.getInstance("RSA");
// Initiate the Cipher, telling it that it is going to Decrypt, giving it the private key
dec.init(Cipher.DECRYPT_MODE, kp);
try {
return EncryptedMessage.getObject(dec);
} catch (ClassNotFoundException | IllegalBlockSizeException | BadPaddingException e) {
e.printStackTrace();
return null;
}
}
}
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package bitcion;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
/**
*
* @author LaNa Sa
*/
public class Serialization {
public static Object deserialize(byte[] bytes) throws IOException, ClassNotFoundException {
try(ByteArrayInputStream b = new ByteArrayInputStream(bytes)){
try(ObjectInputStream o = new ObjectInputStream(b)){
return o.readObject();
}
}
}
public static byte[] serialize(Object obj) throws IOException {
try(ByteArrayOutputStream b = new ByteArrayOutputStream()){
try(ObjectOutputStream o = new ObjectOutputStream(b)){
o.writeObject(obj);
}
return b.toByteArray();
}
}
}
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package bitcion;
/**
*
* @author LaNa Sa
*/
import static bitcion.ClientClass.readKeyPair;
import java.sql.PreparedStatement;
import java.sql.*;
import java.util.Date;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.net.*;
import java.io.*;
import java.math.BigInteger;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.ArrayList;
import java.util.List;
import javax.crypto.SealedObject;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
public class ServerClass extends Thread{
private ServerSocket serverSocket;
private KeyPair myPair;
private PublicKey CAPublicKey;
//for generate sssion key:
private SecureRandom random = new SecureRandom();
public ServerClass(int port) throws IOException {
serverSocket = new ServerSocket(port);
// Get my KeyPair from file:
myPair = readKeyPair();
//get CA publicKey:
CAPublicKey = readCAPublicKey();
}
public String nextSessionId() {
return new BigInteger(130, random).toString(32);
}
public static KeyPair readKeyPair() throws FileNotFoundException
{
BufferedReader br;
try {
br = new BufferedReader(new FileReader("serverPublicKey.txt"));
StringBuilder sb = new StringBuilder();
String line = br.readLine();
while (line != null) {
sb.append(line);
sb.append(System.lineSeparator());
line = br.readLine();
}
String publicK = sb.toString();
//convert public key from String to PublicKey:
byte[] publicBytes = new BASE64Decoder().decodeBuffer(publicK);
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey pubKey = keyFactory.generatePublic(keySpec);
br.close();
br = new BufferedReader(new FileReader("serverPrivateKey.txt"));
sb = new StringBuilder();
line = br.readLine();
while (line != null) {
sb.append(line);
sb.append(System.lineSeparator());
line = br.readLine();
}
String privateK = sb.toString();
//convert private key from String to PublicKey:
byte[] privateBytes = new BASE64Decoder().decodeBuffer(privateK);
PKCS8EncodedKeySpec keySpec2 = new PKCS8EncodedKeySpec(privateBytes);
PrivateKey privKey = keyFactory.generatePrivate(keySpec2);
br.close();
//genrate keyPair:
return new KeyPair(pubKey, privKey);
} catch (IOException ex) {
Logger.getLogger(ClientClass.class.getName()).log(Level.SEVERE, null, ex);
return null;
} catch (NoSuchAlgorithmException ex) {
Logger.getLogger(ClientClass.class.getName()).log(Level.SEVERE, null, ex);
return null;
} catch (InvalidKeySpecException ex) {
Logger.getLogger(ClientClass.class.getName()).log(Level.SEVERE, null, ex);
return null;
}
}
public static PublicKey readCAPublicKey(){
BufferedReader br;
try {
br = new BufferedReader(new FileReader("SystemCAPublicKey.txt"));
StringBuilder sb = new StringBuilder();
String line = br.readLine();
while (line != null) {
sb.append(line);
sb.append(System.lineSeparator());
line = br.readLine();
}
String publicK = sb.toString();
//convert public key from String to PublicKey:
byte[] publicBytes = new BASE64Decoder().decodeBuffer(publicK);
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey pubKey = keyFactory.generatePublic(keySpec);
br.close();
return pubKey;
} catch (FileNotFoundException ex) {
Logger.getLogger(ServerClass.class.getName()).log(Level.SEVERE, null, ex);
return null;
} catch (IOException ex) {
Logger.getLogger(ServerClass.class.getName()).log(Level.SEVERE, null, ex);
return null;
} catch (NoSuchAlgorithmException ex) {
Logger.getLogger(ServerClass.class.getName()).log(Level.SEVERE, null, ex);
return null;
} catch (InvalidKeySpecException ex) {
Logger.getLogger(ServerClass.class.getName()).log(Level.SEVERE, null, ex);
return null;
}
}
public void run() {
while(true) {
try {
System.out.println("Waiting for client on port " +
serverSocket.getLocalPort() + "...");
Socket server = serverSocket.accept();
System.out.println("Just connected to " + server.getRemoteSocketAddress());
ObjectInputStream in = new ObjectInputStream(server.getInputStream());
ObjectOutputStream out = new ObjectOutputStream(server.getOutputStream());
//recive operator number from client:
String operator_number =(String) in.readObject();
System.out.println("operator number: " + operator_number);
switch(operator_number){
case "signUp":
{
//recive certificate from client:
DigitalCertificate cer = (DigitalCertificate) in.readObject();
//verify the recived certification:
boolean verifyResult = cerVerify(cer);
if(verifyResult)
{
//insert client certificate in database:
insertNewClientCertificate(cer);
//reciv client account and save it in database:
SystemClient c = (SystemClient) in.readObject();
insertNewClient(c, cer);
}else
{
System.out.println("Certificate isn't Validate.");
}
break;
}
case "1":
{
//send server publicKey to client:
out.writeObject(myPair.getPublic());
out.flush();
//get clientIP:
String clientIP = (String)in.readObject();
//get client publicKey from DB by ip:
PublicKey clientPK = getClientPublicKey(clientIP);
//generate session key:
String sessionKey = nextSessionId();
//Encrypt session key with RSA:
SealedObject enc_session_key = RSA.encrypt(sessionKey, myPair.getPrivate());
//send session key:
out.writeObject(enc_session_key);
out.flush();
//Sending Data:
List<SystemClient> sendData = getClientTableQuery();
//Encrypt sending data and send(write) it in socket:
SealedObject encrypted_data = AES.encrypt((Serializable) sendData,sessionKey.getBytes());
out.writeObject(encrypted_data);
out.flush();
break;
}
case "2":
{
//send server publicKey to client:
out.writeObject(myPair.getPublic());
out.flush();
//get clientIP:
String clientIP = (String)in.readObject();
//get client publicKey from DB by ip:
PublicKey clientPK = getClientPublicKey(clientIP);
//generate session key:
String sessionKey = nextSessionId();
//Encrypt session key with RSA:
SealedObject enc_session_key = RSA.encrypt(sessionKey, myPair.getPrivate());
//send session key:
out.writeObject(enc_session_key);
out.flush();
//recive transaction from client:
SealedObject EncryptedMessage = (SealedObject) in.readObject();
Transaction recv_message = (Transaction) AES.decrypt(EncryptedMessage,sessionKey.getBytes());
//print transaction on screen
System.out.println(recv_message.toString());
//recive digital signature from client:
DataInputStream din = new DataInputStream(server.getInputStream());
int digital_sig_len = din.readInt();
InputStream srm_in = server.getInputStream();
byte[] digital_sig = new byte[digital_sig_len];
srm_in.read(digital_sig,0,digital_sig_len);
//virefcation of dital seg:
byte[] messageBytes = Serialization.serialize(EncryptedMessage);
boolean ver_result = VerficationSignature.verify(messageBytes, digital_sig, clientPK);
//test validation of transaction:
if(!ver_result)
{
System.out.println("the transaction is rejected...\nSignature isn't correct..");
}else if(getClientAccountValue(recv_message.senderIP) < recv_message.value)
{
System.out.println("the transaction is rejected...\nAccount value is less than transaction value");
out.flush();
out.writeObject(new String("the transaction is rejected...\nAccount value is less than transaction value"));
}else
{
insertTransaction(recv_message,digital_sig.toString());
out.flush();
out.writeObject(new String("Transaction Done Sucssefuly."));
}
break;
}
}
server.close();
}catch(SocketTimeoutException s) {
System.out.println("Socket timed out!");
break;
}catch(IOException e) {
e.printStackTrace();
break;
} catch (Exception ex) {
Logger.getLogger(ServerClass.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
public List<SystemClient> getClientTableQuery()
{
List<SystemClient> result = new ArrayList<SystemClient>();
String host = "jdbc:derby://localhost:1527/Bitcion";
String username = "bitcion";
String password = "bitcion";
try {
Connection con = DriverManager.getConnection( host, username, password );
Statement stmt = con.createStatement();
String SQL = "SELECT * FROM CLIENTS";
ResultSet rs = stmt.executeQuery(SQL);
while(rs.next())
{
SystemClient ct = new SystemClient();
ct.ip =rs.getString("IP");
ct.value =rs.getInt("VALUE");
result.add(ct);
}
} catch (SQLException ex) {
Logger.getLogger(ServerClass.class.getName()).log(Level.SEVERE, null, ex);
}
return result;
}
public int getClientAccountValue(String clientIP)
{
int result = 0;
String host = "jdbc:derby://localhost:1527/Bitcion";
String username = "bitcion";
String password = "bitcion";
try {
Connection con = DriverManager.getConnection( host, username, password );
PreparedStatement statement = con.prepareStatement("select * from CLIENTS where IP = ?");
statement.setString(1, clientIP);
ResultSet rs = statement.executeQuery();
rs.next();
result = rs.getInt("VALUE");
} catch (SQLException ex) {
Logger.getLogger(ServerClass.class.getName()).log(Level.SEVERE, null, ex);
}
return result;
}
public void insertTransaction(Transaction t,String digital_signature)
{
String host = "jdbc:derby://localhost:1527/Bitcion";
String username = "bitcion";
String password = "bitcion";
try {
Connection con = DriverManager.getConnection( host, username, password );
//Insert transaction in transactions tabel:
PreparedStatement statement = con.prepareStatement("INSERT INTO TRANSACTIONS VALUES ( ? , ? , ? , ?) ");
statement.setString(1,t.senderIP);
statement.setString(2,t.reciverIP);
statement.setInt(3,t.value);
statement.setString(4,digital_signature);
statement.execute();
//Update sender account:
statement = con.prepareStatement("UPDATE CLIENTS SET VALUE = VALUE - ? WHERE IP = ?");
statement.setInt(1,t.value);
statement.setString(2,t.senderIP);
statement.execute();
//Update reciver account:
statement = con.prepareStatement("UPDATE CLIENTS SET VALUE = VALUE + ? WHERE IP = ?");
statement.setInt(1,t.value);
statement.setString(2,t.reciverIP);
statement.execute();
} catch (SQLException ex) {
Logger.getLogger(ServerClass.class.getName()).log(Level.SEVERE, null, ex);
}
}
private boolean cerVerify(DigitalCertificate cer){
//test if the CA name is same as the CA of system:
if(!cer.getIssuerName().equals("BitCionCA"))
return false;
//test if CA publicKey is right:
if(!VerficationSignature.verify(cer.cerToByte(), cer.getSignature(), CAPublicKey))
return false;
//test certificate validity:
Date currentDate = new Date();
if(currentDate.after(cer.getValidityFinishDate()))
return false;
return true;
}
private void insertNewClientCertificate(DigitalCertificate cer)
{
String host = "jdbc:derby://localhost:1527/Bitcion";
String username = "bitcion";
String password = "bitcion";
try {
Connection con = DriverManager.getConnection( host, username, password );
//Insert transaction in transactions tabel:
PreparedStatement statement = con.prepareStatement("INSERT INTO CERTIFICATES VALUES ( ? , ? , ? , ? , ? , ? , ?) ");
statement.setInt(1,cer.getSerialNumber());
statement.setString(2,cer.getIssuerName());
statement.setDate(3,new java.sql.Date(cer.getIssuingDate().getTime()));
statement.setDate(4,new java.sql.Date(cer.getValidityFinishDate().getTime()));
statement.setString(5,cer.getSubjectName());
statement.setString(6,cer.getSignature().toString());
//encode public key as string and then store it in DB:
String publicK = new BASE64Encoder().encode(cer.getSubjectPublicKey().getEncoded());
statement.setString(7,publicK);
statement.execute();
} catch (SQLException ex) {
Logger.getLogger(ServerClass.class.getName()).log(Level.SEVERE, null, ex);
}
}
private void insertNewClient(SystemClient c,DigitalCertificate cer)
{
String host = "jdbc:derby://localhost:1527/Bitcion";
String username = "bitcion";
String password = "bitcion";
try {
Connection con = DriverManager.getConnection( host, username, password );
//Insert transaction in transactions tabel:
PreparedStatement statement = con.prepareStatement("INSERT INTO CLIENTS VALUES ( ? , ? , ?) ");
statement.setString(1,c.ip);
statement.setInt(2,c.value);
statement.setInt(3,cer.getSerialNumber());
statement.execute();
} catch (SQLException ex) {
Logger.getLogger(ServerClass.class.getName()).log(Level.SEVERE, null, ex);
}
}
private PublicKey getClientPublicKey(String clientIP){
String host = "jdbc:derby://localhost:1527/Bitcion";
String username = "bitcion";
String password = "bitcion";
try {
Connection con = DriverManager.getConnection( host, username, password );
PreparedStatement statement = con.prepareStatement("select * from CERTIFICATES where SUBJECTNAME = ?");
statement.setString(1, clientIP);
ResultSet rs = statement.executeQuery();
rs.next();
String publicK = rs.getString(7);
//convert public key from String to PublicKey:
byte[] publicBytes = new BASE64Decoder().decodeBuffer(publicK);
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey pubKey = keyFactory.generatePublic(keySpec);
return pubKey;
} catch (SQLException ex) {
Logger.getLogger(ServerClass.class.getName()).log(Level.SEVERE, null, ex);
return null;
} catch (IOException ex) {
Logger.getLogger(ServerClass.class.getName()).log(Level.SEVERE, null, ex);
return null;
} catch (NoSuchAlgorithmException ex) {
Logger.getLogger(ServerClass.class.getName()).log(Level.SEVERE, null, ex);
return null;
} catch (InvalidKeySpecException ex) {
Logger.getLogger(ServerClass.class.getName()).log(Level.SEVERE, null, ex);
return null;
}
}
public static void main(String[] args) {
try {
ServerClass server = new ServerClass(6000);
server.start();
// System.out.println(server.getClientTableQuery());
} catch (IOException ex) {
Logger.getLogger(ServerClass.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package bitcion;
import java.io.*;
/**
*
* @author LaNa Sa
*/
public class SystemClient implements Serializable{
public String ip;
public int value;
@Override
public String toString() {
return "ip :" + ip + ", value :" + value ;
}
}
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package bitcion;
import java.io.*;
/**
*
* @author LaNa Sa
*/
public class Transaction implements Serializable {
public String senderIP;
public String reciverIP;
public int value;
public Transaction() {
}
public Transaction(String senderIP, String reciverIP, int value) {
this.senderIP = senderIP;
this.reciverIP = reciverIP;
this.value = value;
}
@Override
public String toString() {
return "Transaction{" + "senderIP=" + senderIP + ", reciverIP=" + reciverIP + ", value=" + value + '}';
}
}
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package bitcion;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PublicKey;
import java.security.Signature;
import java.security.SignatureException;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* @author LaNa Sa
*/
public class VerficationSignature {
public static boolean verify(byte[] message,byte[] sigToVerify,PublicKey pk)
{
Signature sig;
try {
sig = Signature.getInstance("MD5WithRSA");
sig.initVerify(pk);
sig.update(message);
return sig.verify(sigToVerify);
} catch (NoSuchAlgorithmException ex) {
Logger.getLogger(VerficationSignature.class.getName()).log(Level.SEVERE, null, ex);
return false;
}catch (InvalidKeyException ex) {
Logger.getLogger(VerficationSignature.class.getName()).log(Level.SEVERE, null, ex);
return false;
} catch (SignatureException ex) {
Logger.getLogger(VerficationSignature.class.getName()).log(Level.SEVERE, null, ex);
return false;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment