Created
November 27, 2016 23:04
-
-
Save lnlonSA/48da21e5e1ff11d26bdf218495b43557 to your computer and use it in GitHub Desktop.
المرحلة2 : التوقيع الرقمي + عدم النكران
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* 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 bitcion.forms.Client; | |
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.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; | |
/** | |
* | |
* @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 main(String[] argc) throws FileNotFoundException | |
{ | |
String server_name="localhost"; | |
int port_number=6000; | |
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()); | |
//send operator number to server (2) refer to do transaction: | |
out.writeObject(new String("2")); | |
//get server public key: | |
ObjectInputStream in = new ObjectInputStream(client.getInputStream()); | |
PublicKey serverpk = (PublicKey) in.readObject(); | |
System.out.println("Server Public Key is recived"); | |
//send my public key to server: | |
out.flush(); | |
out.writeObject(myPair.getPublic()); | |
//encrypt transaction object: | |
Transaction message = new Transaction("192.168.1.112", "192.168.1.105",1000); | |
out.flush(); | |
SealedObject EncryptedMessage = RSA.encrypt(message, serverpk); | |
out.writeObject(EncryptedMessage); | |
//get digital signature of encrypted message: | |
out.flush(); | |
byte[] messageBytes = Serialization.serialize(EncryptedMessage); | |
byte[] digital_sig = GenerateSignature.generate(messageBytes, myPair.getPrivate()); | |
//send digital signature to server: | |
DataOutputStream dout = new DataOutputStream(client.getOutputStream()); | |
dout.writeInt(digital_sig.length); | |
OutputStream srm_out = client.getOutputStream(); | |
srm_out.write(digital_sig, 0, digital_sig.length); | |
//finish and close the socket: | |
client.close(); | |
} catch (IOException ex) { | |
Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex); | |
} catch (ClassNotFoundException ex) { | |
Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex); | |
}catch (NoSuchAlgorithmException ex) { | |
Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex); | |
} catch (NoSuchPaddingException ex) { | |
Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex); | |
} catch (InvalidKeyException ex) { | |
Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex); | |
} catch (IllegalBlockSizeException ex) { | |
Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* 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; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* 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; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* 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(); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* 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 bitcion.forms.Client; | |
import java.sql.PreparedStatement; | |
import java.sql.*; | |
import java.util.logging.Level; | |
import java.util.logging.Logger; | |
import java.net.*; | |
import java.io.*; | |
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.List; | |
import javax.crypto.SealedObject; | |
import sun.misc.BASE64Decoder; | |
public class ServerClass extends Thread{ | |
private ServerSocket serverSocket; | |
private KeyPair myPair; | |
public ServerClass(int port) throws IOException { | |
serverSocket = new ServerSocket(port); | |
// Get my KeyPair from file: | |
myPair = readKeyPair(); | |
} | |
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 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()); | |
//recive operator number from client: | |
String operator_number =(String) in.readObject(); | |
System.out.println("operator number: " + operator_number); | |
switch(operator_number){ | |
case "2": | |
{ | |
//send my public Key to client: | |
ObjectOutputStream out = new ObjectOutputStream(server.getOutputStream()); | |
out.writeObject(myPair.getPublic()); | |
//recive client public key: | |
PublicKey clientPK = (PublicKey) in.readObject(); | |
//recive transaction from client: | |
SealedObject EncryptedMessage = (SealedObject) in.readObject(); | |
Transaction recv_message = (Transaction) RSA.decrypt(EncryptedMessage,myPair.getPrivate()); | |
//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"); | |
}else | |
{ | |
insertTransaction(recv_message,digital_sig.toString()); | |
} | |
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); | |
} | |
} | |
public static void main(String[] args) { | |
try { | |
ServerClass server = new ServerClass(6000); | |
server.start(); | |
} catch (IOException ex) { | |
Logger.getLogger(ServerClass.class.getName()).log(Level.SEVERE, null, ex); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* 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 ; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* 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 + '}'; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* 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