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();
}
}