SecureRandom 教程

说实话,作为一个工作了好几年的一个老程序员。我对 SecureRandom 了解的也不是很多,知道最近在读一个框架的源码时遇到了 SecureRandom 这个类。我一下子就被他吸引住了,SecureRandom 类提供加密的强随机数生成器。下面我们一起来学习它吧。

SecureRandom 教程

Random 类中实现的随机算法是伪随机,也就是有规则的随机。在进行随机时,随机算法的起源数字称为种子数(seed),在种子数的基础上进行一定的变换,从而产生需要的随机数字。相同种子数的 Random 对象,相同次数生成的随机数字是完全相同的。也就是说,两个种子数相同的 Random 对象,生成的随机数字完全相同。所以在需要频繁生成随机数,或者安全要求较高的时候,不要使用Random,因为其生成的值其实是可以预测的。

SecureRandom 和 Random 都是,也是如果种子一样,产生的随机数也一样: 因为种子确定,随机数算法也确定,因此输出是确定的。只是说,SecureRandom 类收集了一些随机事件,比如鼠标点击,键盘点击等等,SecureRandom 使用这些随机事件作为种子。这意味着,种子是不可预测的,而不像 Random 默认使用系统当前时间的毫秒数作为种子,有规律可寻。

SecureRandom 内置两种随机数算法,NativePRNG 和 SHA1PRNG。下面我们分别来学习它们。

通过 new 来初始化,默认来说会使用 NativePRNG 算法生成随机数,但是也可以配置 -Djava.security 参数来修改调用的算法,如果是 /dev/[u]random 两者之一就是 NativePRNG,否则就是 SHA1PRNG。在JVM启动时设置下面的参数,即可切换算法。

-Djava.security=file:/dev/urandom 
-Djava.security=file:/dev/random

上面两个设置一个即可,不要重复设置参数。

另外我们也可以通过 SecureRandom.getInstance 获取不同的算法。

SecureRandom secureRandom = new SecureRandom();
SecureRandom secureRandom3 = SecureRandom.getInstance("SHA1PRNG");
SecureRandom secureRandom2 = SecureRandom.getInstance("SHA1PRNG", "SUN");

SecureRandom 提供的一些方法和 Random 类似。通过 nextInt 即可获取随机数。

nextBytes(byte[] bytes) 可以获取随机的一个byte数组,注意这里不是返回,这个方法是void返回类型,是直接随机改变了 test。

SecureRandom random = new SecureRandom();
byte[] test = new byte[20];
random.nextBytes(test);

generateSeed(int numBytes) 方法可以获取一个随机的byte数组,这个数组中的数通常可以用来做其他随机生成器的种子。

byte seed[] = random.generateSeed(20);

产生高强度的随机数,有两个重要的因素:种子和算法。当然算法是可以有很多的,但是如何选择种子是非常关键的因素。

下面看一个简单的例子:

private List<List<Integer>> generateCakes(int num, int seedLength, int rowLen) {
	SecureRandom random = new SecureRandom();
	byte[] seeds = SecureRandom.getSeed(seedLength); //获取随机的byte数组,用来后续作为种子
	int counter = 0;
	int realCount = 0;
	int tmprows = 0;
	List<List<Integer>> CakesList = new ArrayList<List<Integer>>();
	while (num > tmprows) {
		List<Integer> list = new ArrayList<Integer>();
		while (counter < rowLen) {
			random.setSeed(seeds); //设置种子
			int cake = random.nextInt(38); //随机生成0-37的数字
			if (!list.contains(cake) && 0 != cake) {
				list.add(cake);
				counter++;
			}
			random.nextBytes(seeds); //随机获取新的byte数组用以作为下次的种子,不断循环
			realCount++;
		}
		Collections.sort(list);
		pairs++;
		tmprows++;
		counter = 0;
		CakesList.add(list);
		if (pairs % Constants.MSG_COUNT == 0) {
			System.out.println(pairs + " cakes generated.");
		}
	}
	System.out.println("乱数取得回数:" + realCount);
	return CakesList;
}

参考资料

  • SecureRandom的江湖偏方与真实效果
  • Java 随机数 Random VS SecureRandom
  • Java中的随机数生成器:Random,ThreadLocalRandom,SecureRandom(转)
  • Java中生成随机数Random、ThreadLocalRandom、SecureRandom
  • API参考 SecureRandom(示例,出错代码)

SecureRandom 教程

: » SecureRandom 教程

原创文章,作者:Carrie001128,如若转载,请注明出处:https://blog.ytso.com/251721.html

(0)
上一篇 2022年5月3日
下一篇 2022年5月3日

相关推荐

发表回复

登录后才能评论