这个随机整数函数可以用于生成密码吗?

时间:2018-11-29 00:26:34

标签: javascript random

最近我一直在研究随机数,通常只使用Math.Random,因为我不需要使用更安全的方法,但是我认为学习这样的东西会很有用,想知道此功能的安全性/实用性以及我可以实现的一些改进。

function random_number(max) {
    let buffer=new ArrayBuffer(8);
    let ints=new Int8Array(buffer);
    window.crypto.getRandomValues(ints);
    ints[7]=64-1;
    ints[6]|=0xf0;
    let float=new DataView(buffer).getFloat64(0,true)-1;
    return Math.floor(float*Math.floor(max+1));
}

1 个答案:

答案 0 :(得分:0)

不,不是。

您正在有效地执行操作(通过将二进制数据转换为浮点值)正在计算floor(max * rand() / (RAND_MAX + 1.0))(其中RAND_MAX等于2 52 −1) 。除非maxRAND_MAX+1as explained here的因数,否则这总是会导致分布失真。

这很容易证明:

function random_number(max) {
    let buffer=new ArrayBuffer(8);
    let ints=new Int8Array(buffer);
    window.crypto.getRandomValues(ints);
    ints[7]=64-1;
    ints[6]|=0xf0;
    let float=new DataView(buffer).getFloat64(0,true)-1;
    return Math.floor(float*Math.floor(max+1));
}

function check_skew() {
    var m = Math.floor(Math.pow(2,52) * 2 / 3);
    var o = [0,0];
    var ns = 100000;
    for (i=0; i<ns; i++) o[random_number(m)&1]++; o;
    console.log("Out of "+ns+" random numbers, "+o[0]*100/ns+
                "% were even and "+o[1]*100/ns+"% were odd.");
}
<button onclick="check_skew()">Click this button a few times and check the results</button>

获取指定范围内的随机整数的正确方法是从一个统一的随机数开始,该随机数的位长至少应与max的位长一样长。丢弃高位,如果结果小于或等于max,则返回结果。否则,请重复该过程。

也许是这样的

function rand_int(max) {
    // Returns a uniform random integer from 0 to max (inclusive)
    var mask = 1;
    var crypto = window.crypto;
    max = Math.floor(max);

    if (!crypto) throw "window.crypto undefined";
    if (max < 1) throw "max value too small";
    if (max > 0xffffffff) throw "max value too large";

    // Generate binary mask (all 1)
    while (mask < max) mask = (mask << 1) | 1;

    // Now generate random values until one is within range
    var r = new Int32Array(1);
    do {
        crypto.getRandomValues(r);
        r[0] &= mask;
    } while (r[0] > max);
    return r[0];
}