2
votes

I am trying to encrypt a small file with AES (128 bits) and then encrypt the AES key with RSA (1024 bits). This works fine.

As the logical next step I try to decrypt the AES key with RSA.

Decrypting with RSA returns a 128 byte block, but my AES key is just 16 byte long. Upon research I read that I need to use RSA with Padding so i used RSA/ECB/PKCS1Padding.

But this always gives me the following exception -

javax.crypto.BadPaddingException: error:04000089:RSA routines:OPENSSL_internal:PKCS_DECODING_ERROR
at com.android.org.conscrypt.NativeCrypto.RSA_private_decrypt(Native Method)
at com.android.org.conscrypt.OpenSSLCipherRSA$DirectRSA.doCryptoOperation(OpenSSLCipherRSA.java:402)
at com.android.org.conscrypt.OpenSSLCipherRSA.engineDoFinal(OpenSSLCipherRSA.java:314)
at javax.crypto.Cipher.doFinal(Cipher.java:2055)

My KeyPair generation logic -

        KeyPairGenerator keyGen = null;
        try {
            keyGen = KeyPairGenerator.getInstance("RSA");
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        keyGen.initialize(1024);
        byte[] publicKey = keyGen.genKeyPair().getPublic().getEncoded();

        byte[] privateKey = keyGen.genKeyPair().getPrivate().getEncoded();


        Util.save("privateKey", rsa.encryptBASE64(privateKey), this);
        Util.save("publicKey", rsa.encryptBASE64(publicKey), this);

My Encryption logic -

        public static byte[] encryptByPublicKey(byte[] data, String key)
            throws Exception {

        byte[] keyBytes = decryptBASE64(key);


        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        Key publicKey = keyFactory.generatePublic(x509KeySpec);


        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);

        return cipher.doFinal(data);
    }

My Decryption logic -

        public static byte[] decryptByPrivateKey(byte[] data, String key)
            throws Exception {

        byte[] keyBytes = decryptBASE64(key);


        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        Key privateKey = keyFactory.generatePrivate(pkcs8KeySpec);


        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.DECRYPT_MODE, privateKey);

        return cipher.doFinal(data);
    }

Any help will be appreciated.

Could anyone also guide me on how to convert the decrypted RSA block to AES key ?

To test this is whatI do in my code. Encryption and Decryption are back to back steps -

String aesKeyCipherBase64 = rsa.encryptBASE64(rsa.encryptByPublicKey(secretKey.getEncoded(), myPublicKeyString));

byte[] aesKeyRecovered = rsa.decryptByPrivateKey(rsa.decryptBASE64(aesKeyCipherBase64),myPrivateKeyString);

The Base64 Util Method -

public static byte[] decryptBASE64(String key)  {
        return Base64.decode(key, Base64.NO_PADDING|Base64.NO_WRAP|Base64.NO_PADDING|Base64.URL_SAFE);
    }

public static String encryptBASE64(byte[] key)  {
        return Base64.encodeToString(key, Base64.NO_PADDING|Base64.NO_WRAP|Base64.NO_PADDING|Base64.URL_SAFE);
    }
       public static void save(String key, String value, Activity activity) {


        SharedPreferences sharedPref = activity.getSharedPreferences("myapp",Context.MODE_PRIVATE);
        SharedPreferences.Editor editor = sharedPref.edit();
        editor.putString(key, value);
        editor.commit();
    }
        String myPublicKeyString = Util.getPublicKey(this);
        String myPrivateKeyString = Util.getPrivateKey(this);
    public static String getPrivateKey(Activity activity) {

        SharedPreferences sharedPref = activity.getSharedPreferences("myapp",Context.MODE_PRIVATE);
        return sharedPref.getString("privateKey", null);
    }

    public static String getPublicKey(Activity activity) {

        SharedPreferences sharedPref = activity.getSharedPreferences("myapp",Context.MODE_PRIVATE);
        return sharedPref.getString("publicKey", null);
    }
1
There are several possibilities, the most likely two being: 1) the data has been corrupted in transit, 2) the public and private keys do not belong to the same keypair. Perhaps you can explain and provide the code that shows what happens after the data is encrypted, including all the steps until the decrypt method is called. Also, you need to verify the public and private key you are using belong to the same keypair.President James K. Polk
String aesKeyCipherBase64 = rsa.encryptBASE64(rsa.encryptByPublicKey(secretKey.getEncoded(), myPublicKeyString)); byte[] aesKeyRecovered = rsa.decryptByPrivateKey(rsa.decryptBASE64(aesKeyCipherBase64),myPrivateKeyString); This is all i do. Encryption n Decryption a back to back steps. I have updated the question as well.Sijo Josan
My Bad! Updated those 2 methods as well.Sijo Josan
When I run your code it works fine for me.President James K. Polk
Oh! Did you run this on an Android app or just plain java class in your computer? I do have a doubt if the issue is something related to the android os.Sijo Josan

1 Answers

2
votes

I changed the following -

byte[] publicKey = keyGen.genKeyPair().getPublic().getEncoded();

byte[] privateKey = keyGen.genKeyPair().getPrivate().getEncoded();

to -

KeyPair kp = keyGen.genKeyPair();

byte[] publicKey = kp.getPublic().getEncoded();
byte[] privateKey = kp.getPrivate().getEncoded();

I was generating a new KeyPair each to access the public & private key.

Thank you @president-james-moveon-polk for pointing me towards the right direction.