Skip to content

Instantly share code, notes, and snippets.

@lnlonSA
Created November 27, 2016 23:04
Show Gist options
  • Save lnlonSA/48da21e5e1ff11d26bdf218495b43557 to your computer and use it in GitHub Desktop.
Save lnlonSA/48da21e5e1ff11d26bdf218495b43557 to your computer and use it in GitHub Desktop.
المرحلة2 : التوقيع الرقمي + عدم النكران
/*
* 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);
}
}
}
/*
* 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 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);
}
}
}
/*
* 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