我一直在使用Java的SecureRandom类来生成盐,以便以后加密和密码哈希(我为每个任务生成单独的盐)。我一直使用的代码如下:
//Init random number generator
secureRandom = SecureRandom.getInstance("SHA1PRNG");
secureRandom.setSeed(System.nanoTime());
//Create salts
secureRandom.nextBytes(bytAuthSalt);
secureRandom.nextBytes(bytEncryptionSalt);
现在,一切都很顺利,直到我开始真正验证我得到的值。对于应用程序的几个连续执行,我的盐是:
[B@43d55dd8
[B@43d55b58
[B@43d55b50
[B@43bd0cc8
[B@43db0b08
[B@43bd0f50
我对这些数字看起来大致是连续的这一事实感到不安。在网上进行了一些搜索之后,我再次重复了这些运行而没有将它自己播种到相同的结果。
我唯一猜测可能导致这种情况的原因是我正在为Android平台开发。我知道他们有自己的加密提供商,但我没有任何例外。任何想法?
提前致谢。
答案 0 :(得分:9)
看起来您正在打印对字节数组的引用而不是其内容。这就是为什么它们是顺序的,引用基本上是给你JVM内存中的位置。在打印之前将字节数组转换为String。
String saltContents = Arrays.toString(bytAuthSalt);
使用Arrays将数组转换为String将显示字节的原始值。
答案 1 :(得分:4)
似乎您正在打印数组,而不是实际值。 “[B @”告诉你它是一个字节数组,并且它后面的所有对象都是id。
尝试这样的事情:
System.out.println("bytAuthSalt"); for (byte b : bytAuthSalt) { System.out.print(b); } System.out.println();
或者这个:
Arrays.toString(bytAuthSalt);
这将打印数组中的所有值。
答案 2 :(得分:2)
SHA1PRNG仅与其种子一样安全。出于这个原因,使用System.nanoTime()
作为种子是一个可怕的想法。可以充分缩小播种时间范围的攻击者可以尝试所有可能的值,直到找到匹配的序列。攻击者得益于System.nanoTime()
的分辨率通常远大于1纳秒。
最好只做new SecureRandom()
以允许JRE选择最佳实现。在大多数平台上,这将使用OS原生熵源来种子RNG,例如/dev/random
。
答案 3 :(得分:1)
我还建议不要用于播种System.nanoTime()
,因为它不能保证在所有平台上都能正常工作。在某些情况下,它只返回'零',我认为它不适合播种RNG。