Java基础、中级、高级、架构面试资料

SecureRandom 教程

JAVA herman 5957浏览 0评论
公告:“业余草”微信公众号提供免费CSDN下载服务(只下Java资源),关注业余草微信公众号,添加作者微信:xttblog2,发送下载链接帮助你免费下载!
本博客日IP超过2000,PV 3000 左右,急需赞助商。
极客时间所有课程通过我的二维码购买后返现24元微信红包,请加博主新的微信号:xttblog2,之前的微信号好友位已满,备注:返现
受密码保护的文章请关注“业余草”公众号,回复关键字“0”获得密码
所有面试题(java、前端、数据库、springboot等)一网打尽,请关注文末小程序
视频教程免费领
腾讯云】1核2G5M轻量应用服务器50元首年,高性价比,助您轻松上云

说实话,作为一个工作了好几年的一个老程序员。我对 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;
}

参考资料

业余草公众号

最后,欢迎关注我的个人微信公众号:业余草(yyucao)!可加作者微信号:xttblog2。备注:“1”,添加博主微信拉你进微信群。备注错误不会同意好友申请。再次感谢您的关注!后续有精彩内容会第一时间发给您!原创文章投稿请发送至532009913@qq.com邮箱。商务合作也可添加作者微信进行联系!

本文原文出处:业余草: » SecureRandom 教程