在不同的浏览器中,JavaScript 中使用的算法,如 Math.random()
,有多好?它是否适用于生成盐和一次性密码?
从一个 random
中我可以使用多少位?
在不同的浏览器中,JavaScript 中使用的算法,如 Math.random()
,有多好?它是否适用于生成盐和一次性密码?
从一个 random
中我可以使用多少位?
不,JavaScript的Math.random()
函数不是一个安全的加密随机数生成器。你最好使用JavaScript Crypto Library的Fortuna实现,它是一个强伪随机数生成器(请查看src/js/Clipperz/Crypto/PRNG.js
),或者使用Web Crypto API中的getRandomValues
这个PRNG(伪随机数生成器)非常不安全,在某些情况下甚至是可预测的,你可以重建PRNG的内部状态,推导出种子,然后可以用它来跟踪人们在网站间的活动,即使他们没有使用cookies,并且隐藏在洋葱路由之后等...
2022编辑:如果你需要JavaScript中的加密RNG,请使用Crypto.getRandomValues
这篇2008年的论文揭示了浏览器弱PRNG的用户跟踪可能性
这篇稍晚的谷歌Chrome漏洞论文(2009年),因为这个问题早已广为人知
Int8Array
、Uint8Array
、Int16Array
、Uint16Array
、Int32Array
或Uint32Array
),该函数将使用强密码学随机数生成器填充数组。浏览器应该使用强(伪)随机数生成器。 如果请求的长度大于65536字节,则该方法会抛出QuotaExceededError。
示例:var array = new Uint32Array(10);
window.crypto.getRandomValues(array);
console.log("Your lucky numbers:");
for (var i = 0; i < array.length; i++) {
console.log(array[i]);
}
同时,对于JavaScript的Math.random()函数有多随机的回答,请参考此处。此外,来自2008年的一份报告讨论了JavaScript Math.random()函数如何泄漏信息和跨域信息泄露和攻击。
更新:查看Modern.IE Web Crypto API部分可获取当前浏览器支持状态,并且该部分还连接了Chrome、Firefox 和Safari的错误报告。
由于您无法确切知道浏览器的实现(除了像您业务内部网这样的封闭用户组),因此我通常认为RNG是薄弱的。
即使您可以识别浏览器,您也不知道浏览器本身或任何其他浏览器代理ID是否被篡改。如果可以的话,您应该在服务器上生成数字。
即使您在JavaScript中包含一个良好的PRNG,您的服务器也无法知道客户端的请求是否来自未修改的脚本。如果数字进入您的数据库和/或用作加密工具,则不应完全信任来自客户端的数据。这不仅适用于有效性(您确实验证来自客户端的所有数据吗?),而且还适用于一般属性,如随机性。
/**
* This method returns a random number between 0 and 1 (Compatible with Math.random())
* // Compliant for security-sensitive use cases
* @returns Random number between 0 and 1.
*/
export const randomNumber = (): number => {
// RandomBytes generates 4 random bytes, which are then read as a 32-bit unsigned integer in little endian.
// The max value of a 32bit unsigned int is 0xFFFFFFFF (or 4,294,967,295 in decimal).
// By dividing the randomly generated 32bit int by its max value you get a value between 0 and 1.
// eslint-disable-next-line unicorn/number-literal-case
return randomBytes(4).readUInt32LE(0) / 0xffffffff;
};
function numberGenerator(max){
let num = (Date.now() +'');
num = parseInt(num.at(num.length-1));
while(num > max){
num -= max
}
return num;
}
Math.random()
不具备加密安全性。此外,Veracode将用以下方式指出此情况
CWE-331(不足的熵)
我们可以使用SecureRandom来实现类似的功能。
new SecureRandom().nextDouble();