从密码学安全的源创建有偏随机数¶
ID: js/biased-cryptographic-random
Kind: problem
Security severity: 7.5
Severity: warning
Precision: high
Tags:
- security
- external/cwe/cwe-327
Query suites:
- javascript-code-scanning.qls
- javascript-security-extended.qls
- javascript-security-and-quality.qls
生成安全的随机数可能是创建安全软件系统的重要组成部分。这可以通过使用创建密码学安全的随机数的 API 来实现。
但是,对这些密码学安全的随机数使用某些数学运算可能会产生有偏的结果,其中一些结果比其他结果更有可能出现。此类有偏结果会使攻击者更容易猜测随机数,从而破坏软件系统的安全性。
建议¶
在对密码学安全的随机数执行数学运算时,要非常小心不要引入偏差。
如果可能,完全避免对密码学安全的随机数执行数学运算,而是使用现有的库。
示例¶
以下示例使用模运算符来创建包含 10 个随机数字的数组,使用随机字节作为随机性的来源。
const crypto = require('crypto');
const digits = [];
for (let i = 0; i < 10; i++) {
digits.push(crypto.randomBytes(1)[0] % 10); // NOT OK
}
随机字节是 0 到 255 之间的均匀随机值,因此使用模运算符的结果在 0 到 5 之间的可能性略高于在 6 到 9 之间的可能性。
以下代码中通过使用正确生成密码学安全的随机值的库来修复了问题。
const cryptoRandomString = require('crypto-random-string');
const digits = cryptoRandomString({length: 10, type: 'numeric'});
或者,可以通过修复原始代码中的数学运算来修复问题。在以下代码中,如果值大于或等于 250,则丢弃随机字节。因此,模运算符用于 0 到 249 之间的均匀随机数,这会导致 0 到 9 之间的均匀随机数字。
const crypto = require('crypto');
const digits = [];
while (digits.length < 10) {
const byte = crypto.randomBytes(1)[0];
if (byte >= 250) {
continue;
}
digits.push(byte % 10); // OK
}
参考资料¶
Stack Overflow: 理解“随机性”.
OWASP: 不安全的随机性.
OWASP: 规则 - 使用强大的经过批准的加密算法.
常见弱点枚举: CWE-327.