bigywater.tech
Java · 189

SecureRandom:安全随机数如何获得熵

SecureRandom 的随机数从哪来?setSeed 到底做什么?要不要复用实例?这篇用实测回答(普通随机数算法的对比在前两篇,这篇只看安全随机数;熵的来源是操作系统,本篇没有直接观察系统调用)。

NativePRNG / NativePRNGBlocking
默认与 getInstanceStrong 的算法
SHA1PRNG 可复现
其它算法 setSeed 只补充熵
5.0 µs vs 61 ns
每次 new SecureRandom 与复用实例的 nextInt

算法与配置

实测 · 本机执行输出
  new SecureRandom() 的算法 = NativePRNG,提供者 = SUN
  SecureRandom.getInstanceStrong() 的算法 = NativePRNGBlocking,提供者 = SUN
  java.security 里:securerandom.source = file:/dev/random;securerandom.strongAlgorithms = NativePRNGBlocking:SUN,DRBG:SUN
  提供者 SUN 提供的 SecureRandom 算法:[DRBG, NativePRNG, NativePRNGBlocking, NativePRNGNonBlocking, SHA1PRNG]
  DRBG 实例的参数:128,reseed_only,null

setSeed

实测 · 本机执行输出
  SHA1PRNG    两个实例都在第一次使用之前 setSeed(42):输出 d50ac288b90ede2e 与 d50ac288b90ede2e → 完全相同(种子决定了输出)
  NativePRNG  两个实例都在第一次使用之前 setSeed(42):输出 bb500fa0875fc913 与 39842e47a0e6b5ed → 不同(setSeed 只是补充熵,不决定输出)
  DRBG        两个实例都在第一次使用之前 setSeed(42):输出 f9544d6ff4c06a9c 与 ac6a1f775eedf440 → 不同(setSeed 只是补充熵,不决定输出)
  SHA1PRNG 先生成过数据(自己播了种),之后再 setSeed(42):输出 3d18d237fdfe3f97 与 85f28bf50a1afccb → 不同(setSeed 在已播种后只是追加)

耗时

实测 · 本机执行输出
  NativePRNG             创建+首次使用 15766 µs;nextBytes(32) 平均 221 ns/次;generateSeed(32) 38 µs
  DRBG                   创建+首次使用 1257 µs;nextBytes(32) 平均 223 ns/次;generateSeed(32) 59 µs
  SHA1PRNG               创建+首次使用 1940 µs;nextBytes(32) 平均 106 ns/次;generateSeed(32) 55 µs
  NativePRNGNonBlocking  创建+首次使用 195 µs;nextBytes(32) 平均 197 ns/次;generateSeed(32) 15 µs
  每次都 new SecureRandom() 再 nextInt():5.0 µs/次(1000 次);复用同一个实例的 nextInt():61 ns/次

统计检查

实测 · 本机执行输出
  100 万个随机字节:1 的比特占 0.5001(理想 0.5000);256 种字节值的卡方统计量 = 262.7(自由度 255,均值 255,标准差约 22.6;落在 255 ± 3 个标准差 ≈ 187~323 之内是正常的)
  这只是最粗的合理性检查,不是对随机数质量的证明(没有做 NIST / Dieharder 之类的检验)

分步演示

SecureRandom
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / OpenJDK(Temurin 17.0.20、Homebrew 21.0.12 与 27,每篇注明实际用的版本);用 javac 编译、java 直接运行,需要第三方库时用 Maven 解析依赖;计时用 System.nanoTime,数字每次运行会有小幅抖动。JDK 21.0.12,macOS(Linux 上的默认算法与阻塞行为可能不同)
    • 没有验证:操作系统层面实际读取了什么(没有跟踪系统调用)、Linux 的 /dev/random 阻塞行为、DRBG 的 reseed 间隔与 prediction resistance 配置、容器里熵不足时的表现、NIST 级别的统计检验;耗时是一次运行
    京ICP备2026067502号-1京公网安备11010502063487号