I am trying to build group chat application where multiple user in Multicastsocket group can chat. I am performing encryption by encrypting message by AES and then encrypting AES key by RSA.
But at the receiver side when I try to get AES key by RSA decryption , I get Decryption Error specifically at line (cipher.dofinal(text)). I am unable to understand the error . I even checked size of each key in bytes but there was no mathematical error . Please guide me through it
import java.net.*;
import java.io.*;
import java.util.*;
import javax.crypto.Cipher;
//import javax.crypto.KeyGenerator;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.security.*;
class Security
{
public static KeyPair generateRSAkeyPair() throws Exception
{
//SecureRandom secureRandom = new SecureRandom();
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
//KeyGenerator keyGenerator = KeyGenerator.getInstance("RSA");
keyPairGenerator.initialize(4096);
KeyPair pair = keyPairGenerator.generateKeyPair();
return pair;
}
public static byte[] AESEncryption(String plaintext, SecretKey secKey) throws Exception
{
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE,secKey);
byte[] cipherText = cipher.doFinal(plaintext.getBytes());
return cipherText;
}
public static byte[] RSAEncryption(PrivateKey privateKey, SecretKey key) throws Exception
{
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.ENCRYPT_MODE, privateKey);
//cipher.update(plaintext.getBytes());
byte [] encryptedKey = cipher.doFinal(key.getEncoded());
//System.out.println(encryptedKey.length);
return encryptedKey;
}
public static byte[] RSADecryption(byte[] encryptedKey, PublicKey publicKey) throws Exception
{
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.DECRYPT_MODE, publicKey);
//byte check[] = cipher.doFinal(encryptedKey);
//System.out.println(check.length);
return cipher.doFinal(encryptedKey);
}
public static String AESDecryption(byte[] decryptedKey, byte[] text) throws Exception
{
SecretKey originalKey = new SecretKeySpec(decryptedKey , 0, decryptedKey.length, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, originalKey);
byte[] plaintext = cipher.doFinal(text);
return new String(plaintext);
}
KeyPair keyPair;
SecretKey key;
Security()
{
try{
//@SuppressWarnings("unused")
keyPair = generateRSAkeyPair();
KeyGenerator generator = KeyGenerator.getInstance("AES");
generator.init(128); // The AES key size in number of bits
key = generator.generateKey();
}catch(Exception e) {
System.out.println(e);
}
}
static Security s = new Security();
}
public class Symmetra extends Security
{
private static final String TERMINATE = "Exit";
static String name;
static volatile boolean finished = false;
public static void main(String[] args) throws Exception
{
if (args.length != 2)
System.out.println("Two arguments required: <multicast-host> <port-number>");
else
{
try
{
//KeyPair keyPair = generate();
//Security s = new Security();
//SecretKey key = createAESKey();
InetAddress group = InetAddress.getByName(args[0]);
int port = Integer.parseInt(args[1]);
Scanner sc = new Scanner(System.in);
System.out.print("Enter your name: ");
//SocketAddress group = new SocketAddress(args[0],port);
name = sc.nextLine();
MulticastSocket socket = new MulticastSocket(port);
socket.setTimeToLive(3);
socket.joinGroup(group);
Thread t = new Thread(new ReadThread(socket,group,port));
t.start();
System.out.println("Start typing messages...n");
while(true)
{
String message;
message = sc.nextLine();
if(message.equalsIgnoreCase(Symmetra.TERMINATE))
{
finished = true;
socket.leaveGroup(group);
socket.close();
break;
}
//message = name + ": " + message;
//byte[] cipherText = RSAEncryption(message,keyPair.getPrivate());
byte[] cipherText = AESEncryption(message,s.key);
byte[] encryptedKey = RSAEncryption(s.keyPair.getPrivate(), s.key);
System.out.println(cipherText.length + " " + encryptedKey.length);
//byte[] buffer = message.getBytes();
DatagramPacket datagram = new
DatagramPacket(cipherText,cipherText.length,group,port);
DatagramPacket datagram2 = new
DatagramPacket(encryptedKey,encryptedKey.length,group,port);
socket.send(datagram);
socket.send(datagram2);
}
}
catch(SocketException se)
{
System.out.println("Error creating socket");
se.printStackTrace();
}
catch(IOException ie)
{
System.out.println("Error reading/writing from/to socket");
ie.printStackTrace();
}
}
}
}
class ReadThread extends Security implements Runnable
{
private MulticastSocket socket;
private InetAddress group;
private int port;
private static final int MAX_LEN = 1000;
ReadThread(MulticastSocket socket,InetAddress group,int port)
{
this.socket = socket;
this.group = group;
this.port = port;
}
@Override
public void run()
{
while(!Symmetra.finished)
{
//KeyPair keyPair;
//SecretKey key;
try {
//keyPair = generate();
//key = createAESKey();
byte[] buffer = new byte[ReadThread.MAX_LEN];
DatagramPacket datagram = new
DatagramPacket(buffer,buffer.length,group,port);
byte[] keyBuffer = new byte[512];
DatagramPacket datagram2 = new
DatagramPacket(keyBuffer,keyBuffer.length,group,port);
String message;
try
{
socket.receive(datagram);
socket.receive(datagram2);
byte[] decryptKey = RSADecryption(keyBuffer,s.keyPair.getPublic());
String decryptText = AESDecryption(decryptKey, buffer);
//message = new String(decryptText,0,datagram.getLength(),"UTF-8");
message = decryptText;
if(!message.startsWith(Symmetra.name))
System.out.println(message);
}
catch(IOException e)
{
System.out.println("Socket closed!");
}
}
catch (Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
}