Reputation: 21
I am trying to create a RSA encryption chat program between a server and client. However I encounter a bad padding exception when i receive and try to decrypt the message here are my codes.
Please help me! Your help will be greatly appreciated!
Client:
Socket s;
BufferedReader br;
BufferedWriter bw;
TextField text;
Button sendBut, exitBut;
List list;
public client(String st)
{
super(st);
setSize(300, 130);
setLocation(300,0);
setResizable(true);
setBackground(new Color(192, 192, 192));
this.setLayout(new GridLayout(2, 1));
Panel panels[] = new Panel[2];
panels[0] = new Panel();
panels[1] = new Panel();
panels[0].setLayout(new BorderLayout());
panels[1].setLayout(new FlowLayout(FlowLayout.LEFT));
sendBut = new Button("Send");
exitBut = new Button("Exit");
sendBut.addActionListener(this);
exitBut.addActionListener(this);
list = new List();
text = new TextField(25);
panels[0].add(list);
panels[1].add(text);
panels[1].add(sendBut);
panels[1].add(exitBut);
add(panels[0]);
add(panels[1]);
setVisible(true);
try
{
/* Assuming that this application is run on single
machine I've used the default ip i.e., 127.0.0.1. If
you want to use it on 2 different machines use the
ip that is assigned to the machine on which server
applicatin is residing*/
s = new Socket("127.0.0.1", 1053);
br = new BufferedReader(new InputStreamReader(s.getInputStream()));
bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
Thread th;
th = new Thread(this);
th.start();
}catch(Exception e){}
}
public static void main(String arg[])
{
// create an object instance of the class
// by sending the title as parameter
new client("Client Application");
}
public void run()
{
while (true)
{
try
{
String receive = br.readLine();
list.addItem(receive);
byte[] msg1 = receive.getBytes("UTF-8");
//decrypt
//Get pri Key
FileInputStream FISkey1 = new FileInputStream("privatekey.txt");
ObjectInput oi1 = new ObjectInputStream(FISkey1);
Key privateKey = (Key) oi1.readObject();
FISkey1.close();
Cipher cipher1 = Cipher.getInstance("RSA/ECB/PKCS1Padding");
//encrypt the public key
cipher1.init(Cipher.DECRYPT_MODE, privateKey);
byte[] deciphertext = cipher1.doFinal(msg1);
String receivePrint = new String(deciphertext, "UTF-8");
list.addItem(receivePrint);
}catch (Exception h){
}
}
}
public void actionPerformed(ActionEvent ae)
{
if(ae.getSource().equals(exitBut))
System.exit(0);
else
{
try
{
String s = text.getText();
byte[] msg = s.getBytes("UTF-8");
//encrypt
//Get public Key
FileInputStream FISkey = new FileInputStream("publickey.txt");
ObjectInput oi = new ObjectInputStream(FISkey);
Key publicKey = (Key) oi.readObject();
FISkey.close();
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
//encrypt the public key
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] ciphertext = cipher.doFinal(msg);
String send = new String(ciphertext, "UTF-8");
bw.write(send);
bw.newLine();
bw.flush();
text.setText("");
}catch(Exception m){}
}
}
}
Server :
ServerSocket ss;
Socket s;
BufferedReader br;
BufferedWriter bw;
TextField text;
Button sendBut, exitBut;
List list;
public server(String m) // class constructor
{
super(m);
setSize(300, 130);
setLocation(0,0);
setResizable(true);
setBackground(new Color(192, 192, 192));
this.setLayout(new GridLayout(2, 1));
Panel panels[] = new Panel[2];
panels[0] = new Panel();
panels[1] = new Panel();
panels[0].setLayout(new BorderLayout());
panels[1].setLayout(new FlowLayout(FlowLayout.LEFT));
sendBut = new Button("Send");
exitBut = new Button("Exit");
sendBut.addActionListener(this);
exitBut.addActionListener(this);
list = new List();
list.addItem("Server up & Listening on port plz wait...");
text = new TextField(25);
panels[0].add(list);
panels[1].add(text);
panels[1].add(sendBut);
panels[1].add(exitBut);
add(panels[0]);
add(panels[1]);
setVisible(true);
try
{
ss = new ServerSocket(1053);//some port number, better be above 1000
s = ss.accept();
br = new BufferedReader(new InputStreamReader(s.getInputStream()));
bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
bw.write("Hi! Please Enter Your Message Here");
bw.newLine();
bw.flush();
Thread th;
th = new Thread(this);
th.start();
}catch(Exception e){}
}
public void run()
{
while (true)
{
try
{//string toDecrypt = br.readLine();
//decrypt;
list.addItem(br.readLine());
}catch (Exception e){}
}
}
public static void main(String arg[])
{
// create an object instance
// by sending the title as a parameter
new server("Server Applicaton");
}
public void actionPerformed(ActionEvent ae)
{
if (ae.getSource().equals(exitBut))
System.exit(0);
else
{
try
{
String s = text.getText();
byte[] msg = s.getBytes("UTF-8");
//encrypt
//Get public Key
FileInputStream FISkey = new FileInputStream("publickey.txt");
ObjectInput oi = new ObjectInputStream(FISkey);
Key publicKey = (Key) oi.readObject();
FISkey.close();
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
//encrypt the public key
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] ciphertext = cipher.doFinal(msg);
String send = new String(ciphertext, "UTF-8");
bw.write(send);
bw.newLine();bw.flush();
text.setText("");
}catch(Exception x){}
}
}
Please help me! Your help will be greatly appreciated!
Upvotes: 2
Views: 4381
Reputation: 150
I know it is too old but thought of adding my observations.
I was using Web Crypto API with javascript at the front end which encrypted the small string with the public key and Java at the backend for decrypting that back using private key.
Below is the code for decryption where the issue was:
// cipherText is encrypted cipher
byte[] base64DecodedSmallString = Base64.getDecoder().decode(cipherText);
Cipher rsaCiphar = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
// pvt_key contains private key
rsaCipharinit(Cipher.DECRYPT_MODE, pvt_key);
rsaCiphar.doFinal(base64DecodedSmallString);
At the doFinal method, I faced "javax.crypto.BadPaddingException
"
And there could be multiple reasons for this exception(the exception message is not very helpful).
The issue was Cipher.getInstance method where I provided only the RSA/ECB/OAEPWithSHA-256AndMGF1Padding
as transformation, so I experimented using an overloaded method getInstance(String transformation, Provider provider)
and used the provider called bouncy castle (https://bouncycastle.org/java.html).
The only change required in the code was :
Cipher rsaCiphar = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding"
, "BC");
After which the decryption worked!!
FYI: BC stands for Bouncy Castle.
Upvotes: 0
Reputation: 42744
A Bad padding Exception is often an indicator that the decryption has failed.
Possible reasons:
In your case it is most likely option 2 - the changed cipher text because you are converting the binary cipher text to a String. Strings are for printable characters only!
Send the cipher text as byte-array and see if it solves your problem.
Upvotes: 3
Reputation: 1702
I'll add one more reason of how you can get a Bad Padding exception. It's a dumb stupid reason but I accidentally did this and you'll end up going down the wrong path trying to solve it.
When I decrypted the text, I forgot to pass the cipher the text to decrypt. So when you call cipher.doFinal() you get a Bad Padding exception.
Upvotes: 0
Reputation: 94038
You treat the ciphertext as string. Each byte of the ciphertext may contain any value. This can result in data loss, as not every byte value may have a representative as a character in the string.
Upvotes: 1