I am trying to RSA encrypt some data in python using a public key that was generated by a client in android. The encryption goes successfully (atleast there are no exceptions). However, when trying to decrypt the data using the private key in android it throws a bad padding exception.
Relevant Code :
Generating RSA Key Pair in Android. A cutdown version of Bouncy castle is included in android:
import javax.crypto.KeyGenerator;
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(2048);
return kpg.generateKeyPair();
Encryption in Python :
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP
import base64
from Crypto.Hash import SHA256
# key contains the public key string without any line breaks.
def encrypt(keyString, plainText)
key = key.replace('-----BEGIN PUBLIC KEY-----', '')
key = key.replace('-----END PUBLIC KEY-----', '');
pubkey = RSA.importKey(base64.b64decode(key))
cipher = PKCS1_OAEP.new(pubkey, hashAlgo=SHA256)
encrypted = cipher.encrypt(plaintext)
return base64.b64encode(encrypted)
print encrypt('-----BEGIN PUBLIC KEY-----MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA7fJDt9my7WTnPahyw9JvIwm/q3F9jF9R2qNv01Os5NhBUgWOha67DlalOhQmQYBosnXfTWm6JQF2upnBInFGUOZx+10UVnuUbTpUT004lBfNbHx23rrf66b48Q25OoDnbWM3xWD8+9GPvoLO3ftJSbcjb+euzVJOkJYNo33dnG0yZ4LWHLBMog7OgbnjjobiM+O/0wzmiW8VE7gCrg7ZyGpxHXo9ACJytKjC4Hg976Ryg1wyrD2dmgiV212CcBGdzj7F6xn1Uyk7DTeAOgQJHLDFr+2sHgcXJXyslrjvCp3Om2CbzDY9W8XaU2A/84Q1Ejt8ljtJZBOJCuH+ARqZRwIDAQAB-----END PUBLIC KEY-----', 'this is a test string')
Decryption in Android. A cutdown version of Bouncy castle is included in android :
Relevant Imports :
import javax.crypto.Cipher;
import javax.crypto.spec.OAEPParameterSpec;
import javax.crypto.spec.PSource;
import java.security.spec.MGF1ParameterSpec;
import java.util.*;
import android.util.Base64;
Decryption :
private static String RSA_CONFIGURATION = "RSA/ECB/OAEPWithSHA-256AndMGF1Padding";
private static String RSA_PROVIDER = "BC";
public static decrypt(Key key, String encryptedString){
Cipher c = Cipher.getInstance(RSA_CONFIGURATION, RSA_PROVIDER);
c.init(Cipher.DECRYPT_MODE, key, new OAEPParameterSpec("SHA-256", "MGF1", MGF1ParameterSpec.SHA1,
PSource.PSpecified.DEFAULT));
byte[] decodedBytes = c.doFinal(Base64.decode(base64cypherText.getBytes("UTF-8"), Base64.DEFAULT));
clearText = new String(decodedBytes, "UTF-8");
}
Exception :
javax.crypto.BadPaddingException: data hash wrong
at com.android.org.bouncycastle.jcajce.provider.asymmetric.rsa.CipherSpi.engineDoFinal(CipherSpi.java:478)
at javax.crypto.Cipher.doFinal(Cipher.java:1204)
at org.ambientdynamix.security.CryptoUtils.decryptRsa(CryptoUtils.java:204)
Test Keys :
-----BEGIN PRIVATE KEY-----MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDt8kO32bLtZOc9qHLD0m8jCb+rcX2MX1Hao2/TU6zk2EFSBY6FrrsOVqU6FCZBgGiydd9NabolAXa6mcEicUZQ5nH7XRRWe5RtOlRPTTiUF81sfHbeut/rpvjxDbk6gOdtYzfFYPz70Y++gs7d+0lJtyNv567NUk6Qlg2jfd2cbTJngtYcsEyiDs6BueOOhuIz47/TDOaJbxUTuAKuDtnIanEdej0AInK0qMLgeD3vpHKDXDKsPZ2aCJXbXYJwEZ3OPsXrGfVTKTsNN4A6BAkcsMWv7aweBxclfKyWuO8Knc6bYJvMNj1bxdpTYD/zhDUSO3yWO0lkE4kK4f4BGplHAgMBAAECggEBAOJGCeOhoCdkVwopT8msKYeWU7DDYfLFCl/yH/tEjRuqEqPfKOMzgCpodwM9+gs8A1QCB3HkYuGh/LgCUslgEtAH9MhmgVqkdkdQurAW7QDXib/qtFemOh4sUHta45Qg1PMO8RA/5RPK+vjeB77Moar5/zcBiRczeAbCywF4Re/jiimNS2ukINH9o0LlGVHnbj470se/efuXskE7M5kiV8/vnJVvisY5dglwzQHZYyphCeVlnYDQmaTkBrN6j3Gseik0rah3h8DA9Yr7IOZcNXIIPjaYP/cfuIr45tNUXK3K4RC1dV1LUha9fvieZKNoUNTTo06+BWX5+raVEVr3fPECgYEA+JFeZ+3ITPeE57c8ywlz/KdQLW69sHV0iySDrB6zaunaJB5e4Cug5KVYRLCEVMvjUftY+VY5lhA57Cb/jkgXqUYeWZQLndEgXe54kvNtKUgNbY50akxrJvN14vI2J9mXiu7TbvDrVvl/1uxMnHX0VRPnjmCUFYEboAdN496l170CgYEA9Q+YRY/9TKClPLrk9DY8W/NohvdKQBBGW/113Fiq4VunV8M5bhuonjlZY2s7xEDkwZFWzcDsGrT46peASlF7HDJtq0YFR4LrQRXWakiIJzR67GpNHycCbT032dFalIKUngMhoqdzWucRohMJKsQajMZnWeU8QQoZ1Ck20yD3M1MCgYBK/6GafhZXkr9ZIuKG6H1EmD8K1kUJvwbBDO1lu4WrFpApIbjCrqdHFdSCNThYVYRrMglwgeGyM4cmh8XH6lypSGzT3mV64qR/cvqSbDxdnk3e5oKdqB0UjZTeOvK4J2EgHFtTOAHqJjG6aWXcN4LXQMA3J1DHBEOPj2SjAoTLiQKBgQDPZiBgFwmv1XGi4SWuDUyuIWXAe/9qEpwJdIxQLPaJ/ZC19PJg3qWpKy4ctv+BC87Oh5uoTPNFcw4LNKcNvsHrTj6EqqEDMai6j6nEj5gzXfX+qcSVbeVe4GWpQcZgU9dFl67aws8dCtxgh63FdOxnYe7MJPcGsG7FoQ/WRVsRIwKBgQCsHPiywaFb9UiFtMLG23+3LBmcBTz/9YwVfk6p3t34agDq31DdHTj01wZMfXoexkWRAZpKEwcTh/yI75j9K/MjOHgKRb9WYNpyndQy0smgW8DP6LPuRe7yH7Ys0XVTZM4HupGd9xf9AfmKXpd+kS1s/YN8gJDhFySAVsUVCYsKaw==-----END PRIVATE KEY-----
-----BEGIN PUBLIC KEY-----MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA7fJDt9my7WTnPahyw9JvIwm/q3F9jF9R2qNv01Os5NhBUgWOha67DlalOhQmQYBosnXfTWm6JQF2upnBInFGUOZx+10UVnuUbTpUT004lBfNbHx23rrf66b48Q25OoDnbWM3xWD8+9GPvoLO3ftJSbcjb+euzVJOkJYNo33dnG0yZ4LWHLBMog7OgbnjjobiM+O/0wzmiW8VE7gCrg7ZyGpxHXo9ACJytKjC4Hg976Ryg1wyrD2dmgiV212CcBGdzj7F6xn1Uyk7DTeAOgQJHLDFr+2sHgcXJXyslrjvCp3Om2CbzDY9W8XaU2A/84Q1Ejt8ljtJZBOJCuH+ARqZRwIDAQAB-----END PUBLIC KEY-----
OAEP padding has two parameters:
I see in Java you use SHA-256 and MGF1 with SHA-1 hash. They must be not matching to parameters used by Python.
Difference between Python and Java is that Python code uses the same digest for message digesting and mask digesting. While Java (Sun provider and BouncyCastle provider) use SHA-1 for mask digesting by default. So one need to specify all parameters explicitly:
byte[] cipherTextBytes = DatatypeConverter.parseBase64Binary(cipherText);
byte[] privateKeyBytes = DatatypeConverter.parseBase64Binary(privateKeyStr);
KeyFactory kf = KeyFactory.getInstance("RSA");
PKCS8EncodedKeySpec ks = new PKCS8EncodedKeySpec(privateKeyBytes);
PrivateKey privateKey = kf.generatePrivate(ks);
Cipher c = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
c.init(Cipher.DECRYPT_MODE, privateKey, new OAEPParameterSpec("SHA-256",
"MGF1", MGF1ParameterSpec.SHA256, PSource.PSpecified.DEFAULT));
byte[] plainTextBytes = c.doFinal(cipherTextBytes);
String plainText = new String(plainTextBytes);
System.out.println(plainText);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With