PBE AES_256 加密在 java 8 u65 和 u71 之间不兼容

PBE AES_256 encryption incompatible between java 8 u65 and u71

我使用 PBE AES_256 加密了一些文本并将其存储在数据库中。这最初是使用 java 1.8.0_65 完成的。升级到最新的 java 后,我无法再解密这些字段。我已经指出 1.8.0_71 的不兼容性。发行说明说明如下:

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)

所以我假设我需要迁移这些字段值 'manually',方法是用旧版本解密,存储普通值,然后用当前版本重新加密。有没有更好的方法来做到这一点,或者我可能错过了关于这种不兼容性的一些东西?

这是用于加密的部分代码:

 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);

解决方案 我能够通过对我的密码进行一些反射魔术并重新初始化它来解密现有值。如果有人感兴趣,这是代码:

Object spi = ReflectionTestUtils.getField(cipher, "spi");
ReflectionTestUtils.setField(spi, "keyLength", 128);
cipher.init(Cipher.DECRYPT_MODE, keyFromPassword, new PBEParameterSpec(
        salt, iterations, new IvParameterSpec(iv)));

迁移字段值听起来是一种合理的方法。

看着actual code change related to JDK-8138589 看起来并不太复杂。

区别似乎只是密钥长度。因此,即使在 1.8.0_71 之后的版本中,您也应该能够重现旧值。

如果您检测到使用旧 Java 版本创建但现在 运行 在 "new" Java 版本上创建的值,您可以迁移它。已保存的附加字段表示迁移成功。