I encountered the abovementioned exception while I was decrypting a string.
Below is my code:
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import javax.crypto.Cipher;
public class EncryptAndDecrypt {
public static Cipher createCipher () throws Exception{
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
return cipher;
}
public static KeyPair generateKey () throws NoSuchAlgorithmException{
KeyPairGenerator keyGen = KeyPairGenerator.getInstance ("RSA");
keyGen.initialize(1024);
KeyPair key = keyGen.generateKeyPair();
return key;
}
public static byte [] encrypt (String str, Cipher cip, KeyPair key) {
byte [] cipherText = null;
try {
byte [] plainText = str.getBytes("UTF8");
cip.init(Cipher.ENCRYPT_MODE, key.getPublic());
cipherText = cip.doFinal(plainText);
} catch (Exception e) {
e.printStackTrace();
}
return cipherText;
}
public static String decrypt (byte [] c, Cipher cip, KeyPair key) throws Exception {
cip.init(Cipher.DECRYPT_MODE, key.getPrivate());
byte [] decryptedPlainText = cip.doFinal (c);// exception occurred here
String decryptedPlainStr = new String (decryptedPlainText);
return decryptedPlainStr;
}
}
//separate class below to use the encrypt method
public class EncryptionApp {
public static void main (String [] args) {
getEncrypted();
}
public static byte [] getEncrypted () {
byte [] encyptedByte = null;
try {
String plainText = "der";
Cipher cip = Safety.createCipher();
KeyPair key = Safety.generateKey();
encyptedByte = Safety.useRSA(plainText, cip, key);
}
catch (Exception e) {
e.printStackTrace();
}
return encyptedByte;
}
}
// Another class to use the decrypt method
public class DecryptionApp {
public static void main(String[] args) {
System.out.println (useDecrypted () );
}
public static byte[] useDecrypted () {
byte [] decryptedText = null;
try {
Cipher cip = EncryptAndDecrypt.createCipher();
KeyPair key = EncryptAndDecrypt.generateKey();
decryptedText = EncryptAndDecrypt.decrypt(EncryptionApp.getEncrypted(),cip,key);
}
catch (Exception e) {
e.printStackTrace();
}
return decryptedText;
}
}
You already asked the same question in "javax.crypto.BadPaddingException: Data must start with zero" exception, and I gave you an answer: you're using two different keypairs : one to encrypt, and another one to decrypt. That can't work. I even gave you a code sample showing that everything ran fine if you used the same keypair.
KeyPairGenerator.generateKeyPair() generates a keypair. Calling this method twice will get you two different keypairs: it uses a random number generator internally to generate always different keypairs.
You must generate a keypair once, store it in a variable, and use this variable to encrypt and decrypt.
You should read the documentation of the classes and methods you are using. The documentation of generateKeyPair says:
This will generate a new key pair
every time it is called.
Add this main method to EncryptAndDecrypt, and execute it. You'll see that evrything works fine.
public static void main(String[] args) throws Exception {
String s = "hello";
Cipher cipher = createCipher();
KeyPair keyPair = generateKey();
byte[] b = encrypt(s, cipher, keyPair);
String s2 = decrypt(b, cipher, keyPair);
System.out.println(s2);
}
The problem lies in the way you're using this class.
The useDecrypted
method does the following:
Cipher cip = EncryptAndDecrypt.createCipher(); // create a Cipher object using EncryptAndDecrypt
KeyPair key = EncryptAndDecrypt.generateKey(); // generate a KeyPair using EncryptAndDecrypt
// call EncryptionApp.getEncrypted() to get an encrypted text, then decrypt this encrypted text
// using the keypair created above.
decryptedVote = EncryptAndDecrypt.decrypt(EncryptionApp.getEncrypted(), cip, key);
And the getEncrypted
method does the following:
String plainText = "der"; // create some plain text
// create a Cipher instance. Is it the same algorithm as the one in useDecrypted?
// we don't know, because it uses another, unknown, Safety class
Cipher cip = Safety.createCipher();
// create a new KeyPair instance. Is it the same KeyPair as the one in useDecrypted?
// No : another keypair is generated. There is no way something encrypted using a keypair
// will decrypt correctly with another keypair.
KeyPair key = Safety.generateKey();
encyptedByte = Safety.useRSA(plainText, cip, key);
So, in short, you use two different keypairs : one to encrypt and the other to decrypt. That can't work.
Also, note that in encrypt
, you transform your string into a byte array using the UTF8 encoding, whereas in decrypt
, you transform the byte array into a String using the default platform encoding. You should use UTF8 for both, and thus use the following code in decrypt :
String decryptedPlainStr = new String (decryptedPlainText, "UTF8");
Have you googled? A lot of people have this problem when the key to encrypt is not the same as the key to decrypt. It seems like you generate new keys all the time instead of using the same key to decrypt that you used for encryption.
I was getting this error and it turned out in my case to be that the base 64 string I was sending as a parameter contained some characters that were being altered because of being in a URL. The solution turned out to be URL encoding the parameter.