跳到主要内容

随机数

2023年02月14日
柏拉文
越努力,越幸运

一、Math.random()


1.1 获取 [n,m] 的随机整数

实现

function getRandomInt(min,max){
return Math.floor(Math.random()*(max-min+1))+min
}
console.log(getRandomInt(2,4));

二、Web Crypto API


2.1 获取 [n,m] 的随机整数

思路:

实现:

  • 递归方式

    function getRandomInt(min, max) {
    const max_range = 1 << 8;
    const range = max - min + 1;
    const byteArray = new Uint8Array(1);
    window.crypto.getRandomValues(byteArray);
    if (byteArray[0] >= ((max_range / range) << 0) * range) {
    return getRandomInt(min, max);
    }
    return min + (byteArray[0] % range);
    }

    const randomInt = getRandomInt(2, 10);
    console.log(randomInt);
  • 迭代方式

    function getRandomInt(min, max) {
    const max_range = 1 << 8;
    const range = max - min + 1;
    const byteArray = new Uint8Array(1);
    while (true) {
    window.crypto.getRandomValues(byteArray);
    if (byteArray[0] < ((max_range / range) << 0) * range) {
    return min + (byteArray[0] % range);
    }
    }
    }

    const randomInt = getRandomInt(2, 10);
    console.log(randomInt);

三、Node Crypto API


3.1 获取 [n,m] 的随机整数

实现

const crypto = require("crypto");

function getRandomInt(min, max) {
return crypto.randomInt(min,max+1)
}
console.log(getRandomInt(2, 4));

四、方案对比及问题


4.1 通过 Math.random() 方案获取随机数有什么缺陷? 有什么安全性的问题?

Math.random() 返回的数字是伪随机数。计算机是一种具有确定性的机器, 因此不可能产生真正的随机数。伪随机数生成器(PRNG)近似于随机算法,始于一个能计算后续数值的种子。

PRNG 包括两种类型: **统计学的PRNG**和密码学的PRNG

  • **统计学的PRNG**提供了很多有用的统计属性,输出结果很容易预测,因此容易复制数值流。在对安全性要求较高的环境中, 使用能够生成可预测值的函数作为随机数据源, 会产生 Insecure Randomness 错误。Math.random 就是统计学的PRNG,攻击者很容易猜到其生成的字符串。因此, Math.random 这种伪随机数生成器可以快速的计算出看起来很随机的数值,但是不使用用于加密计算。

  • 密码学的PRNG 生成的输出结果很难预测,可解决这一问题。可以解决可预测值的问题, 保证了值的加密安全。因此, 密码学PRNG计算随机数的速度虽然慢了许多,但是生成的值很难预测, 可以用于加密。

参考资料


为什么不建议使用 Math.random 生成随机数