我使用 java.security.SecureRandom
和 "SHA1PRNG"
算法来生成加密 key 。这是用于加密不太重要的数据的历史代码。然而,当我们从java8切换到java11时,我们的代码停止工作。这是重现这种情况的测试用例:
@Test
void srEncryptionSeedTest() throws NoSuchAlgorithmException
{
final long versionSalt = 1850498708034063014L;
final long customSalt = -919666267416765972L;
final SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
sr.setSeed(versionSalt);
final long l1 = sr.nextLong();
final long l2 = sr.nextLong();
sr.setSeed(customSalt);
final long k1 = sr.nextLong();
final long k2 = sr.nextLong();
// check l1 and l2
Assert.assertEquals(l1, 6338935000439666355L);
Assert.assertEquals(l2, -7355545655857008441L);
// Seeding
// check k1 and k2
Assert.assertEquals(k1, -2226559466996804670L); //
Assert.assertEquals(k2, -3123855249705841778L);
}
这在 java11 上工作正常,但在 java8 上我们有 k1=-4273821888324981770
和 k2=3053251164341917236
,因此测试失败。正如您所看到的,在生成相同数量的相同随机数后设置完全相同的种子后,测试开始失败,因此我怀疑 RNG 的状态不同,但调试对我没有帮助(我无法理解为什么它不同)。这可以在任何操作系统上轻松重现。
有关 Java8 JVM 的一些事实:
java.vendor -> Oracle Corporation // same goes on OpenJDK builds
java.version -> 1.8.0_202-ea // same goes on 1.8.0_181
java.vm.info -> mixed mode
java.specification.version -> 1.8
java.runtime.name -> Java(TM) SE Runtime Environment
有关 Java11 JVM 的一些事实:
java.vendor -> AdoptOpenJDK
java.version -> 11.0.3
java.vm.info -> mixed mode
java.specification.version -> 11
java.runtime.name -> OpenJDK Runtime Environment
任何帮助将不胜感激。
最佳答案
[免责声明]: 不要这样做(除非您想要向后兼容)。如果你想要可预测性,你应该基于可靠的 RNG 来实现你的解决方案,我也是如此。但不幸的是,我们必须支持旧文件版本的格式,而且这些文件不包含任何敏感或个人数据,但我们不希望用户更改这些数据,因为这些数据以类似文本的格式存储,因此很容易被更改。
我没有实现我自己的“SHA1PRNG”,因为它太难了(在评论中提到)。相反,我破解了较新的 PRNG 版本,使其行为与旧版本完全相同。原因是,自 java9 OpenJDK 创建者决定制作新版本的 secureRandomSpi 来每次 SecureRandom 重置
setSeed()被调用,旧版本没有。remCount
整数字段的值。
如果你想实现这个 hack,你要做的第一件事是通过调用 "SUN".equals(secureRandom.getProvider().getName()) && "SHA1PRNG".equals(secureRandom.getAlgorithm());
来检查 SecureRandom
实例是否真正是 SUN 的“SHA1PRNG”,然后通过反射获取它的 SPI 并保存其值remCount
字段。然后您可以调用 setSeed()
并将保存的值安装回 remCount
字段。我不想在这里发布这段晦涩的代码,但你已经明白了。谢谢。
关于java - 在 java11 上播种后,SHA1PRNG SecureRandom 行为有所不同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57142890/