2011-01-13 117 views
1

我一直在与Java的SecureRandom类一起工作,以生成盐用于以后的加密和密码散列(我为每个任务生成单独的盐)。我一直在使用的代码如下:Java和密码学强随机数

//Init random number generator 
secureRandom = SecureRandom.getInstance("SHA1PRNG"); 
secureRandom.setSeed(System.nanoTime()); 

//Create salts 
secureRandom.nextBytes(bytAuthSalt); 
secureRandom.nextBytes(bytEncryptionSalt); 

现在,一切都很好,直到我开始真正验证我得到的值。对于应用程序的几个连续执行我的盐是:

[[email protected] 
[[email protected] 
[[email protected] 
[[email protected] 
[[email protected] 
[[email protected] 

我对这些数字似乎都大致顺序感到不安。在网络上进行了一些搜索之后,我再次重复了这些运行,而没有将它自己播种到相同的结果。

我唯一的猜测是什么可能是由于我正在为Android平台开发的事实。我知道他们有自己的密码提供者,但我没有任何例外。有任何想法吗?

在此先感谢。

回答

9

看起来你打印出的是字节数组的引用而不是其内容。这就是为什么它们是连续的,参考基本上是给你在JVM内存中的位置。在打印之前将字节数组转换为字符串。

String saltContents = Arrays.toString(bytAuthSalt); 

阵列转换到使用Arrays将显示字节的原始值的字符串。

+3

如果我没有弄错,那将使用默认字符集来解释字节,而不是打印出原始字节。 OP不需要原始字节而不是ASCII等效字符? – 2011-01-13 16:49:08

+1

@ RD01 - 但仍然会给OP一个很好的随机性视图。 – Rogach 2011-01-13 16:50:57

4

似乎您正在打印一个数组,而不是实际值。 “[B @”告诉你它是一个字节数组,而它后面的所有对象都是id。
尝试是这样的:

System.out.println("bytAuthSalt"); 
    for (byte b : bytAuthSalt) { 
    System.out.print(b); 
    } 
    System.out.println(); 

或者这样:

Arrays.toString(bytAuthSalt); 

这将打印数组的所有值。

1

我也建议不要使用播种System.nanoTime(),因为它不能保证在所有平台上正常工作。在某些情况下,它只返回'零',我认为这是不适合播种RNG的数字。

2

SHA1PRNG只与其种子一样安全。出于这个原因,使用System.nanoTime()作为种子是一个可怕的想法。可以充分缩小播种时间范围的攻击者可以尝试所有可能的值,直到他找到匹配序列。攻击者得益于这样的事实:System.nanoTime()的分辨率通常比1纳秒大得多。

只要做new SecureRandom()就可以让JRE选择最好的实现。在大多数平台上,这将使用OS本地熵源来播种RNG,例如/dev/random