随机数
随机数指在一定范围内、事先无法预测的数值。程序里用到的绝大多数其实是伪随机数(PRNG):由一个确定性算法从种子(seed)推算出的序列——只要种子相同,产出的序列就完全相同,看起来随机但本质可复现。真正的随机数(TRNG)则来自物理熵源(如硬件噪声、时钟抖动),不可复现。
常见用途包括:生成密码与令牌、生成 UUID、打乱顺序或抽样、造测试数据、模拟与游戏。工作方式上,PRNG 内部维护一个状态,每次调用更新状态并输出一个值;种子决定整条序列的走向,这也是为什么固定种子能让结果可重放。
使用中最常见的误区是拿普通 PRNG 去做安全用途。
- 像
Math.random()、C 的rand()是为速度/统计分布设计的,输出可被预测,绝不能用于密码、密钥、会话 token。 - 安全场景要用密码学安全随机源(CSPRNG):浏览器
crypto.getRandomValues()、Nodecrypto.randomBytes()、Pythonsecrets、Gocrypto/rand。 - 别自己用时间戳当种子或手写"洗牌"算法,容易引入偏差和可预测性。
常见问题
Math.random() 能用来生成密码或登录 token 吗?
不能。它是为性能和分布设计的普通伪随机数,内部状态可被逆推、输出可被预测。密码、密钥、token 必须用 CSPRNG,例如浏览器的 crypto.getRandomValues() 或 Node 的 crypto.randomBytes()。
伪随机数和真随机数有什么区别?
伪随机数由确定性算法加种子生成,种子相同结果就相同,可复现;真随机数来自物理熵源(如硬件噪声),不可复现。日常开发中用的几乎都是伪随机,安全需求靠 CSPRNG 满足而非追求物理真随机。
为什么我设了固定种子,每次跑出来的随机数都一样?
这是伪随机数的正常特性,不是 bug。相同种子必然产生相同序列,正好用于测试复现和调试。需要每次不同就用系统随机种子,或直接改用不带固定种子的安全随机源。