如何在JAVA中使用seedBytes使SecureRandom保持不变?

时间:2021-06-03 13:51:48

标签: java android kotlin

我有一个 kotlin android 应用程序,我需要使用种子字节来生成安全随机数。如何使安全随机为相同的种子字节提供相同的数字? 这是我的代码:

val seedBytes = byteArrayOf(116,-64,24,11,126,59,70,-12,68,-39,-33,65,-38,-88,-75,87,97,-112,-22,-64,12,44,-2,-41,-28,-52,82,107,-109,-66,47,41,-59,-44,-114,-95,80,-83,37,107,27,-93,-38,-116,37,-60,-97,98,-102,-61,-50,-83,69,27,11,-12,116,26,59,21,116,69,-90,-19);
val RANDOM = SecureRandom(seedBytes);
println(RANDOM) // => I want this print to always be the same

但现在例如有一次我得到

java.security.SecureRandom@c708450

还有一次我得到

java.security.SecureRandom@de2e6b1

3 个答案:

答案 0 :(得分:1)

您不是从随机中获取值,而是打印您创建的随机实例。您不能每次都将其设置为相同,但是例如,如果您调用 nextInt(),则在两种情况下都是相同的。

答案 1 :(得分:1)

你已经做到了。你对那个输出有点困惑。

<块引用>

System.out.println(someObj)

这只是 System.out.println(someObj.toString()); 的语法糖。

toString() 中的默认 java.lang.Object 实现是这样的:

public String toString() {
    return this.getClass().getName() + "@" + printAsHex(System.identityHashCode(this));
}

换句话说,@c708450 是您 SecureRandom 实例的系统身份哈希码。这是,大大简化,它的内存地址。重点是:如果您有 2 个相同的引用,则编号相同。这就是它所做的一切,否则毫无意义,系统中的每个对象都有这个,它与 Random / SecureRandom 以及 SecureRandom 实例所在的堆内存中的位置没有任何关系,对它吐出的随机数的影响为零。换句话说,@foo 的东西不是种子值。这是一个没有任何意义的数字,除非它与另一个身份哈希码相同。

Random 的 API 不提供获取种子值的方法,也不提供从中获取“距离”的方法。因此,如何确定 SecureRandom 的两个独立实例将永远产生相同的序列并不是很明显。

但是,在实践中,只需对两者调用 .nextInt() 100 次,如果出现相同的 100 个数字?请放心。

因此,如果您想打印安全随机数所在位置的“足迹”,请打印一些 .nextInt().nextByte() 调用。这不仅仅涉及 System.out.println(theSecureRandomInstance) - 没有简单的出路;您必须编写一个方法来执行此操作(当然,请注意这会推进序列。您也不能将它们推回)。

答案 2 :(得分:0)

所以我的解决方案是扩展android的SecureRandom,然后使用java原始代码重新实现它,该代码允许使用相同的种子生成相同的安全随机数。使用 Android 内置的 Secure random 无法做到这一点,因为使用相同种子创建相同随机的可能性已在 Android N 中被弃用,并在 Android P 中被删除

相关问题