2

I am using AES encrypting with bouncy castle implementation in both Android and in a Java servlet environment. The encryption part is ok in both scenario. However I get different result for those 2 platforms once I encrypt the same text with same key.

My intention is to do an encryption in Android and do the decryption in web environment.

This is the only change I have done for Android AES implementation.

    KeyGenerator kgen = KeyGenerator.getInstance("AES");
    SecureRandom sr = null;
    if (android.os.Build.VERSION.SDK_INT >= JELLY_BEAN_4_2) {
        sr = SecureRandom.getInstance("SHA1PRNG", "Crypto");
    } else {
        sr = SecureRandom.getInstance("SHA1PRNG");
    }
    sr.setSeed(key);
    kgen.init(128, sr);
    SecretKey skey = kgen.generateKey();
    byte[] raw = skey.getEncoded();

Above I just add the Crypto into get instance.

I used the spongy castle implementation as well to see whether I can accomplish this. Still it gave me the same result as Android gives. Not sure whether I have loaded it properly. I tested this on API level 14 and 17.

This leads to javax.crypto.BadPaddingException: pad block corrupted.

Dilshan
  • 3,231
  • 4
  • 39
  • 50
  • 1
    Do not use SecureRandom to do this. It is wrong. – kroot Feb 15 '13 at 04:17
  • How should I use it then? – Dilshan Feb 15 '13 at 05:48
  • We can't see your mistake unless you post the encryption code from the Android part and the decryption code from the servlet part. The key generation code you provided is irrelevant. – Duncan Jones Feb 15 '13 at 08:05
  • Actually, what you posted might be relevant if you can explain what `key` is? – Duncan Jones Feb 15 '13 at 08:06
  • Servlet part work as the same. However based on @kroot answer above I went on searching and seems like he has also faced the same issue earlier. Found the needed info from his thread. – Dilshan Feb 15 '13 at 08:08
  • 1
    `SecureRandom` is used to generate random numbers. If you provide a seed in production code, you're doing something wrong. Using a seed is fine to get reproducible behavior in a test, but misses the point of generating random numbers if its used in your actual crypto code. – CodesInChaos Feb 15 '13 at 11:08
  • 1
    Either use `key` directly as AES key, or use a specialized key-derivation-function. Don't abuse `SecureRandom` as KDF. HKDF is pretty simple to implement, and is a great choice to derive multiple keys from a master key. If the key is actually a password, you need to use a password based KDF instead, such as PBKDF2. – CodesInChaos Feb 15 '13 at 11:09

1 Answers1

4

For anyone who is referencing this thread this is the change I did to my code. Now it works well in Android and server environment.

Answer is taken from,

Android 4.2 broke my encrypt/decrypt code and the provided solutions don't work

Thanks @kroot

    /* Store these things on disk used to derive key later: */
    int iterationCount = 1000;
    int saltLength = 32; // bytes; should be the same size as the output
                            // (256 / 8 = 32)
    int keyLength = 256; // 256-bits for AES-256, 128-bits for AES-128, etc
    byte[] salt = new byte[saltLength]; // Should be of saltLength

    /* When first creating the key, obtain a salt with this: */
    SecureRandom random = new SecureRandom();
    random.nextBytes(salt);

    /* Use this to derive the key from the password: */
    KeySpec keySpec = new PBEKeySpec(new String(key,
            Constants.CHAR_ENCODING).toCharArray(), key, iterationCount,
            keyLength);
    SecretKeyFactory keyFactory = SecretKeyFactory
            .getInstance("PBEWithSHA256And256BitAES-CBC-BC");
    byte[] keyBytes = keyFactory.generateSecret(keySpec).getEncoded();
    SecretKey secretKey = new SecretKeySpec(keyBytes, "AES");

    return secretKey.getEncoded();
Community
  • 1
  • 1
Dilshan
  • 3,231
  • 4
  • 39
  • 50