27

I am using RSA to encrypt username and password on Android and decrypt them on server (tomcat 6, java 1.6). Android Encryption:

    PublicKey pubKey = readPublicKeyFromFile(mod, ex);
    Cipher cipher = Cipher.getInstance("RSA");
    cipher.init(Cipher.ENCRYPT_MODE, pubKey);
    byte[] cipherData = cipher.doFinal(data);
    return cipherData;

Java Tomcat Decryption:

    PrivateKey pubKey = readPrivateKeyFromFile(mod, ex);
    Cipher cipher = Cipher.getInstance("RSA");
    cipher.init(Cipher.DECRYPT_MODE, pubKey);
    byte[] cipherData = cipher.doFinal(data);
    return cipherData;

If I use the android part OUTSIDE android (Just in a main method) it works fine. But not inside my android (Emulator). On de server side I get the following error:

javax.crypto.BadPaddingException: Blocktype mismatch: 0
    at sun.security.rsa.RSAPadding.unpadV15(RSAPadding.java:311)
    at sun.security.rsa.RSAPadding.unpad(RSAPadding.java:255)
    at com.sun.crypto.provider.RSACipher.a(DashoA13*..)
    at com.sun.crypto.provider.RSACipher.engineDoFinal(DashoA13*..)
    at javax.crypto.Cipher.doFinal(DashoA13*..)

I keep the mod and ex as BigIntegers constants so I don't write them in to a file. I know that there are difference between java1.6 and java 1.5 encryption, so both are compiled with java 1.6.

Some debug info:

During debug in android I can see that pubKey contains modulus and exponent in hexadecimal. And if I debug in a main method (again the same code) I can see that pubKey contains modulus and exponent in decimal.

What am I doing wrong?

Thanks

bsobat
  • 650
  • 1
  • 6
  • 12

3 Answers3

44

Im doing RSA Encrypt in Android 2.2+ and decrypt on a tomcat 6 java 1.6 server.

I was getting this exact problem, reading all over the place and in part thanks to @Femi 's answer I came across what I needed.

The solution was to use the folowing algorithm specification for the Cipher:

Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");

This works doing encryption from both Android and BlackBerry smartphones. I know its been four months since the question was asked, but just in case someone else goes through this problem.

Maarten Bodewes
  • 90,524
  • 13
  • 150
  • 263
blindstuff
  • 18,298
  • 10
  • 47
  • 48
  • 4
    To confirm, this solution still works in Android 4.x and Java 8. Basically, if you do Cipher.getInstance("RSA") it won't work, you need to specify the more specific one. – sam Feb 22 '15 at 13:12
  • This works as well when decrypting data encrypted in JS. In my case using Cipher.getInstance("RSA") without "/ECB/PKCS1Padding" was adding some extra characters before the needed data. – DH28 Mar 11 '16 at 16:19
  • Thank you. Saved me – Mohit Jul 29 '16 at 22:54
  • How do you actually use this Cipher method? I get 'Unresolved reference: Cipher' – metamonkey Jul 20 '21 at 16:37
13

I suggest you use specific cipher initialization: as an example,

Cipher cipher = Cipher.getInstance("RSA/ECB/NoPadding");

will work on both. The exception you are getting (BadPaddingException) is occuring because the default cipher initialization padding appears to be different between the desktop JVM and the Android JVM.

Femi
  • 64,273
  • 8
  • 118
  • 148
2

Firstly, it looks like you're initializing both ciphers with the public key. Encryption uses public key, decryption used private key. I hope that's just a typo though.

I had a lot of trouble with RSA encryption as well, much was trial and error. I suggest you try another provider. I managed to implement RSA using BouncyCastle.

Cipher wrapper = Cipher.getInstance("RSA", "BC");
wrapper.init(Cipher.ENCRYPT_MODE, publicKey);
encryptedData= wrapper.doFinal(unencryptedData);

Although, I generated my own keypair since this was a session encryption.

kpg = KeyPairGenerator.getInstance("RSA");
        kpg.initialize(1024);
        KeyPair kp = kpg.genKeyPair();
        publicKey = kp.getPublic();
        privateKey = kp.getPrivate();
  • +1 because after hours of trial and error I found this post and it solved my problem. You saved my ass today, thanks :D – Master_T Dec 16 '12 at 13:17
  • Creation of own key pair is insecure as trust needs to be established for the public key. Furthermore, specifying a provider is not a portable way to code, and the default key algorithm may change. Just specifying the full algorithm, including the padding mode (as in the other answers), should be preferred to this solution. – Maarten Bodewes Jan 29 '17 at 21:35
  • How do you actually use this Cipher method? I get 'Unresolved reference: Cipher' – metamonkey Jul 20 '21 at 16:37