import java.net.*; import java.io.*; import javax.crypto.*; import javax.crypto.spec.*; import java.security.*; import sun.misc.*; import java.security.cert.Certificate; import java.security.cert.CertificateFactory; import java.security.spec.*; public class myClient { private Socket socket = null; private DataInputStream console = null; private DataOutputStream streamOut = null; public myClient(String serverName, int serverPort,String clientuser,String serveruser) throws Exception { System.out.println("Establishing connection. Please wait ..."); try { socket = new Socket(serverName, serverPort); System.out.println("Connected: " + socket); start(); } catch(UnknownHostException uhe) { System.out.println("Host unknown: " + uhe.getMessage()); } catch(IOException ioe) { System.out.println("Unexpected exception: " + ioe.getMessage()); } String line = ""; //get public certificate.(signed) //get private key CertificateFactory certfac = CertificateFactory.getInstance("X.509"); // //get CA CERT gen cert. closest filestream // FileInputStream CA = new FileInputStream ("rootca.cer"); // Certificate CACert = certfac.generateCertificate(CA); // CA.close(); // //ca cert get public // PublicKey CACertPub=CACert.getPublicKey(); //need name for server user, generate server cert FileInputStream server = new FileInputStream (serveruser+".crt"); Certificate serverCert = certfac.generateCertificate(server); ByteArrayOutputStream buffer = new ByteArrayOutputStream(); //generating the signature of the server cert int nRead; byte[] data = new byte[1024]; while ((nRead = server.read(data, 0, data.length)) != -1) { buffer.write(data, 0, nRead); } buffer.flush(); server.close(); // //verifying the Server Cert with // File file = new File(serveruser+".sig"); // byte[] sigBytes = new byte[(int) file.length()]; // FileInputStream fis = new FileInputStream(file); // fis.read(sigBytes); // fis.close(); // boolean veri=verifySig(data,CACertPub,sigBytes); // if(veri==true){ // get private key from .keystore PrivateKey ClientPriv=(PrivateKey)getKeyfromkeystore(clientuser); Key AESKey=AESGen(); byte[] objectbyte=changetobyte(AESKey); System.out.println(asHex(AESKey.getEncoded())); //send aes key in encrypt format byte[] aessend=RSAEncryption(serverCert.getPublicKey(),ClientPriv ,objectbyte); streamOut.write(aessend,0,aessend.length); streamOut.flush(); byte[] signatureaes=signData(aessend,ClientPriv); streamOut.writeUTF(AESEncrypt(AESKey,asHex(signatureaes))); streamOut.flush(); while (!line.equals("..bye")) { try { line = console.readLine(); //encrypt line if (line.length()<200){ String encryptedline =AESEncrypt(AESKey,line); //sign the encrypted line byte[] signature=signData(getfromhex(encryptedline),ClientPriv); //send line over streamOut.writeUTF(line); streamOut.flush(); streamOut.writeUTF(AESEncrypt(AESKey,asHex(signature))); streamOut.flush(); //send the signature over } else System.out.println("ERROR message too long"); } catch(IOException ioe) { System.out.println("Sending error: " + ioe.getMessage()); } } // }else // System.out.println("Error, Someone is Impersonating the person you are talking to."); } public void start() throws IOException { console = new DataInputStream(System.in); streamOut = new DataOutputStream(socket.getOutputStream()); } public void stop() { try { if (console != null) console.close(); if (streamOut != null) streamOut.close(); if (socket != null) socket.close(); } catch(IOException ioe) { System.out.println("Error closing ..."); } } public static void main (String args[]) throws Exception { myClient client = null; if (args.length != 4) System.out.println("Usage: java myClient host port yourname serverusername"); else client = new myClient(args[0], Integer.parseInt(args[1]),args[2],args[3]); } public static byte[] signData(byte[] data, PrivateKey key) throws Exception { Signature signer = Signature.getInstance("SHA1withRSA"); signer.initSign(key); signer.update(data); return (signer.sign()); } public byte[] changetobyte(Key AESKey){ Object Aesobj= new Object(); Aesobj = (Object)AESKey; byte[] objectbyte =null; try{ //Change Object to byte format ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutput out = null; out = new ObjectOutputStream(bos); out.writeObject(Aesobj); objectbyte = bos.toByteArray(); out.close(); bos.close(); }catch(Exception e){ System.out.println(e); } return objectbyte; } public Key AESGen(){ //generate aes Key AESKey = null; try{ KeyGenerator keyGenerator = KeyGenerator.getInstance("AES"); keyGenerator.init(128); AESKey = keyGenerator.generateKey(); } catch(Exception e){ System.out.println(e); } return AESKey; } public Key getKeyfromkeystore(String alias){ final String keystoreName = "./.keystore"; final String keystorePassword = "123123123aA"; KeyStore ks = null; Key key=null; try{ ks= KeyStore.getInstance("jks"); ks.load(new FileInputStream(keystoreName), keystorePassword.toCharArray()); key = ks.getKey(alias+"signed", keystorePassword.toCharArray()); }catch (Exception e){ System.out.println(e); } return key; } public static boolean verifySig(byte[] data, PublicKey key, byte[] sig) throws Exception { Signature signer = Signature.getInstance("SHA1withRSA"); signer.initVerify(key); signer.update(data); return (signer.verify(sig)); } public byte[] RSAEncryption(PublicKey ServerPub,PrivateKey ClientPriv,byte[] Aestxt){ //encrypts the AES key with private key then public key byte[] seccipher = null; try{ Cipher cipher = Cipher.getInstance("RSA/ECB/NoPadding"); cipher.init(Cipher.ENCRYPT_MODE,ClientPriv); byte[] firstcipher=cipher.doFinal(Aestxt); cipher.init(Cipher.ENCRYPT_MODE,ServerPub); seccipher= cipher.doFinal(firstcipher); } catch(Exception e){ System.out.println(e); } return seccipher; } public String AESEncrypt(Key AESKey, String PlainTxt){ //get instance of AES //Encrypt data byte[] ciphertxt = null; try{ Cipher c = Cipher.getInstance("AES"); //SecretKeySpec k =new SecretKeySpec(AESKey, "AES"); c.init(Cipher.ENCRYPT_MODE, AESKey); byte[] Ptxt=getfromhex(PlainTxt);; ciphertxt=c.doFinal(Ptxt); } catch(Exception e){ System.out.println(e); } return asHex(ciphertxt); } public static byte[] getfromhex(String s){ int len =s.length(); byte[] data=new byte[len/2]; for(int i=0;i<len;i+=2){ data[i/2] = (byte)((Character.digit(s.charAt(i),16)<<4) + Character.digit(s.charAt(i+1),16)); } return data; } public static String asHex (byte buf[]) { //Obtain a StringBuffer object StringBuffer strbuf = new StringBuffer(buf.length * 2); int i; for (i = 0; i < buf.length; i++) { if (((int) buf[i] & 0xff) < 0x10) strbuf.append("0"); strbuf.append(Long.toString((int) buf[i] & 0xff, 16)); } // Return result string in Hexadecimal format return strbuf.toString(); } }