安全随机数生成器(CSPRNG)
密码学安全伪随机数生成器(CSPRNG)能够保证其生成的随机数完全不可预测。CSPRNG 通过下一位测试,能够抵抗状态泄露扩展攻击,通常是操作系统的一部分,或来自安全的外部来源。根据所需的安全级别,CSPRNG 可以实现为软件组件、硬件设备,或二者的组合。
例如,信用卡制卡中心的正式安全规定要求使用经过认证的硬件随机数生成器,来生成信用卡 PIN 码、私钥及其他应当保密的数据。
现代操作系统(OS)从环境噪声中收集熵(初始种子),包括键盘按键、鼠标移动、网络活动、系统 I/O 中断、硬盘活动等。例如,Linux 中的环境随机性来源包括按键之间的时间间隔、某些中断之间的时间间隔,以及其他同时具有非确定性且难以被外部观察者测量的事件。
操作系统收集的随机性通常可以通过 /dev/random 和 /dev/urandom 访问。
- 读取
/dev/random文件(有限的阻塞式随机数生成器)时,会从内核的熵池中返回熵(收集到的噪声);当熵池为空时,读取会阻塞,直到收集到更多环境噪声。 - 读取
/dev/urandom文件(无限的非阻塞式随机数生成器)时,会从内核熵池返回熵,或返回根据先前收集的环境噪声生成的伪随机数据。后者同样不可预测,但依赖安全的熵“扩展”算法。
通常,CSPRNG 应当使用来自操作系统、专用硬件或外部来源的不可预测随机种子启动。种子初始化后的随机数一般由伪随机计算生成,但这不会损害安全性。大多数算法还会在获得新熵时频繁对 CSPRNG 进行“重新播种”,使其运行更加不可预测。
现代操作系统的 CSPRNG API 通常会把从环境中持续收集的熵与内置伪随机算法的内部状态结合起来,并不断重新播种,从而在同时保持高速、非阻塞行为的情况下,最大限度地保证所生成随机性的不可预测性。
硬件随机数生成器(TRNG)
硬件随机数生成器也称为真随机数生成器(TRNG),通常会捕获可见光谱、环境热噪声、大气噪声等物理过程或现象。来自物理环境的随机性由专用传感器收集,再由设备放大和处理,最后通过 USB、PCI Express 或其他标准接口传输给计算机。
现代微处理器(CPU)提供内置硬件随机数生成器,可以通过专用 CPU 指令 RdRand 访问;该指令会向某个 CPU 寄存器返回一个随机整数。
如今,大多数密码学应用并不需要硬件随机数生成器,因为操作系统中的熵对于一般密码学用途已经足够安全。银行和金融应用、证书颁发机构以及大规模支付处理系统等安全要求更高的系统,才需要使用 TRNG。
开发者如何访问 CSPRNG?
开发者通常通过其语言和平台的密码学库来访问操作系统提供的密码学强随机数生成器(CSPRNG)。
- 在 Linux 和 macOS 中,
/dev/random与/dev/urandom两种随机性来源都被认为对大多数密码学用途足够安全,大多数密码学库会在内部访问它们。 - 在 Windows 中,可以使用下一代密码学 API(CNG)中的
BCryptGenRandom函数或更高级的密码学库,安全地生成用于密码学用途的随机数。 - 在 C# 中,使用 .NET Framework 或 .NET Core 的
System.Security.Cryptography.RandomNumberGenerator.Create()。 - 在 Python 中,使用
os.urandom()或secrets库。 - 在 Java 中,使用
java.security.SecureRandom系统类。 - 在 JavaScript 中,客户端(Web 浏览器)使用
window.crypto.getRandomValues(Uint8Array);服务端(Node.js)使用crypto.randomBytes()或node-sodium等外部模块。
出于密码学目的,绝不要使用 Math.random() 或类似的不安全随机数生成函数!