这段随机数生成代码为什么这么写?

2023-01-11 17:12:03 +08:00
 jaredyam
Random random = new Random();
random.setSeed(new SecureRandom().nextInt());
random.nextInt();

是乱写的,还是有什么考虑?请大神指点一二。

3397 次点击
所在节点    Java
28 条回复
chendy
2023-01-11 17:15:37 +08:00
随机基础上再随机…
其实直接 new SecureRandom().nextInt() 就行了
因为种子一样随机的序列也是一样的,所以外面这一层 Random
chendy
2023-01-11 17:15:54 +08:00
@chendy #1 所以外面这一层 Random 没用了…
Ediacaran
2023-01-11 17:16:04 +08:00
种子足够随机
jaredyam
2023-01-11 17:18:55 +08:00
@Ediacaran 原来这块代码种子的随机数位数也要更大些
jaredyam
2023-01-11 17:19:43 +08:00
@chendy 我现在是没想通它这个加层种子是想干啥,而且一个是 Random ,一个又是 Secure 的
sunny352787
2023-01-11 17:20:51 +08:00
总得给个种子吧,至于种子来源其实无所谓

常用的当前时间做种子理论上来说确实有被攻击的可能,所以这样写算是更安全的写法
不过实际上我觉得这人是想的有点多,除非是纯客户端程序在本地包个虚拟机强行改时间,不然的话用服务器当前时间戳作为随机数种子我觉得没啥问题
sunny352787
2023-01-11 17:24:30 +08:00
@jaredyam 通常的想法是 Random 要比 SecureRandom 性能高,SecureRandom 比 Random 更安全,这样用应该类似 https 的设计,用高安全性的 RSA 来传递密钥,然后用高性能的对称算法来执行加密过程,基本都是这种设计思路
CEBBCAT
2023-01-11 17:27:17 +08:00
我推测是希望获得安全的随机数,但又希望减少来自 SecureRandom 的阻塞。

但如果说要评价写得好不好,应该在完成设计目标的前提下,考察随机性和必要性。即 SecureRandom().nextInt() 是否带来了足够的墒、new Random()的函数是不是安全的。以及可不可以直接使用 SecureRandom().nextInt()。
jaredyam
2023-01-11 17:27:57 +08:00
@sunny352787 所以你是说这个过程没问题是吧。

> 总得给个种子吧

这句话可以再解释下吗?和直接 Random.nextInt()有什么区别呢?也是出于安全的考虑?
ysc3839
2023-01-11 17:28:17 +08:00
SecureRandom 应该是用系统的安全随机数,Random 应该是纯算法的伪随机数。
个人感觉这么做,如果后面是从 random 对象中取多个随机数的话,会降低安全性。如果只取一次问题不大。
sunny352787
2023-01-11 17:28:24 +08:00
@jaredyam 另外,SecureRandom 本身在 Linux 等系统下使用的是操作系统的熵计算,也就是真随机数,但熵源不足的情况下会造成阻塞
ipwx
2023-01-11 17:29:34 +08:00
SecureRandom 的默认参数所使用的种子可能来自于( Posix 上)/dev/random 。而 /dev/random 是个有限的真随机序列,其内容来自于对机器硬件数据的采集。比如网卡的噪音、温度传感器、鼠标键盘动作等。

通过 SecureRandom 得到一个普通伪随机生成器 Random 的初始 seed ,可以有效地得到一个不可预测的随机序列。
sunny352787
2023-01-11 17:31:57 +08:00
@jaredyam 过程没问题,而且确实比用时间做种子更安全

大部分的语言的默认随机数生成器的实现都是需要设置一个种子的,不然默认种子为 0 ,也就是每次启动程序随机出来的序列都是一模一样的
大部分随机数生成算法就是一个迭代公式,用上一个结果计算下一个随机数,那么第一个数从哪来呢?就是你给的种子呗
tinybaby365
2023-01-11 17:35:10 +08:00
random.nextInt();只一次,不如 new SecureRandom().nextInt()

random.nextInt();有限次,挺好

random.nextInt();很多次,看实际情况判断
CEBBCAT
2023-01-11 17:37:23 +08:00
虽然还没人问,但我推荐阅读一下 /dev/urandom 和 /dev/random 的文章,好像和前几年那些 Linux 书本不同,现在即使在加密场景下,也推荐使用 /dev/urandom ,说是已经足够安全了,又不会阻塞。
h0099
2023-01-11 17:42:46 +08:00
zankard
2023-01-11 18:11:56 +08:00
https://metebalci.com/blog/everything-about-javas-securerandom/ 可以看看这个,使用 random 看你对安全性的要求,里面有一个破解程序,只需要知道连续两个随机数,很快就能算出 seed 了,这时候使用 securerandom 作为 seed 与否并不不能保证安全的。
zankard
2023-01-11 18:19:46 +08:00
@zankard 不是连续的随机数,应该也可以运算,就是计算量就更大了。
realpg
2023-01-11 19:36:27 +08:00
不搞密码学应用 不用考虑这些问题

在座诸位 99.999999%用随机数的场景都只是需要一个随机一点的值来实现逻辑,而不是基于随机性进行安全化
kkhaike
2023-01-11 21:16:00 +08:00
这是对的。SecureRandom 应该是使用系统熵的真随机。使用这个作为伪随机的种子能够做到更好的效果。
因为在分布式 /多实例场景下,使用时间作为种子也很容易得到初冲突。

c++11 后也是这样的,参考 https://learn.microsoft.com/zh-tw/cpp/standard-library/random?view=msvc-170 最后一个实例
go 也有使用 crypto/rand 设置 math/rand 种子的用法

主要原因是真随机的获取非常慢。不适合在业务场景下使用。这种方式能够兼得随机性与速度的最好效果(甚至可以在多线程场景下分线程创建以避免锁开支)

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/908198

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX