Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PBE AES_256 encryption incompatible between java 8 u65 and u71

I have some text encrypted and stored in a db using PBE AES_256. This was initially done using java 1.8.0_65. After upgrading to latest java, I can no longer decrypt these fields. I have pinpointed the incompatibility to 1.8.0_71. The release notes state the following:

Problem with PBE algorithms using AES crypto corrected An error was corrected for PBE using 256-bit AES ciphers such that the derived key may be different and not equivalent to keys previously derived from the same password. JDK-8138589 (not public)

So I assume I need to migrate those field values 'manually', by decrypting with the old version, storing the plain value and subsequently re-encrypting with the current version. Is there a better way to do it or am I perhaps missing something regarding this incompatibility?

Here is part of the code that is used for encryption:

 SecretKey keyFromPassword =
        SecretKeyFactory.getInstance(
            algorithm).generateSecret(
            new PBEKeySpec(password.toCharArray()));

 Cipher cipher = Cipher.getInstance(algorithm);
 cipher.init(Cipher.ENCRYPT_MODE, keyFromPassword, new PBEParameterSpec(
        salt, iterations, new IvParameterSpec(iv)));
 IOUtils.copyLarge(new CipherInputStream(clearStream, cipher), encryptedStream);

Solution I was able to decrypt the existing values by doing some reflection magic on my cipher and re-initializing it. Here is the code if anyone is interested:

Object spi = ReflectionTestUtils.getField(cipher, "spi");
ReflectionTestUtils.setField(spi, "keyLength", 128);
cipher.init(Cipher.DECRYPT_MODE, keyFromPassword, new PBEParameterSpec(
        salt, iterations, new IvParameterSpec(iv)));
like image 377
kpentchev Avatar asked Jul 15 '16 09:07

kpentchev


1 Answers

Migrating the field values sounds like a reasonable approach.

Looking at the actual code change related to JDK-8138589 does not look too complicated.

The difference seems to be just the key length. Therefore you should be able to reproduce the old value even on versions after 1.8.0_71.

In case you detect an an value created with an old Java version but now running on a "new" Java version you could migrate it. A successful migration is indicated by and additional field that is saved.

like image 118
Robert Avatar answered Dec 03 '22 13:12

Robert