「随机」两个字,在不同场景里完全是两回事。你手机抽奖的随机、网站验证码的随机、摇号彩票的随机,背后机制天差地别。用错地方,轻则游戏不公平,重则密码被秒破。
伪随机:算法 + 种子
电脑默认生成的「随机数」几乎都是伪随机:由一个确定性算法,从一个叫「种子」的初始值不断推算下一个数。经典算法是线性同余生成器(LCG)。
关键问题:只要知道算法和种子,整个序列可预测。很多语言的 `rand()` 默认种子是系统时间,看起来随机,但同一秒运行结果相近;更糟的是,如果种子固定(比如测试时设了固定种子),每次跑出来完全一样。
真随机:物理噪声
真随机来自物理世界的不可预测性:电路热噪声、放射性衰变、鼠标移动间隔、环境声波。Linux 的 `/dev/random`、Intel 的 RDRAND 指令都从硬件噪声取熵。这部分不可预测、不可复现,是密码学的基石。
为什么密码学不能用普通随机
如果你用 `Math.random()` 生成密码或密钥,攻击者只要知道你用的语言、版本、运行时间,就能缩小猜测范围到极小。这就是为什么 密码生成器 必须用密码学安全随机数(CSPRNG),它基于真随机种子 + 经密码学验证的算法,预测难度在算力层面不可行。用 随机数生成器 做游戏、抽签没问题,但生成密钥、验证码、token 必须用 CSPRNG。
场景对照表
- 游戏抽卡、抽奖、模拟:伪随机足够,要的是「看起来公平」。
- 验证码、session token、密码:必须 CSPRNG(真随机种子)。
- 科学蒙特卡洛模拟:需要可复现时用固定种子伪随机;需要无偏时用真随机。
一个常见坑:洗牌算法
新手洗牌常用「每个位置随机选一个交换」,但这会产生有偏排列(某些顺序出现概率更高)。正确做法(Fisher–Yates)是「从剩余元素里等概率选」,保证每种排列等可能。细节决定公平。
结论
随机不是「看起来乱」就够。日常娱乐用 普通随机数生成器 没问题;但凡是涉及安全、金钱、身份的,认准密码学安全随机——这是 专业密码工具 和普通玩具的本质区别。