节点:使用crypto.randomBytes生成6位数的随机数

时间:2018-07-13 12:40:31

标签: node.js algorithm cryptography

由于0不是2的幂,因此随机产生从9999991000000的精确值的正确方法是什么?

这是我的方法:

  1. 使用crypto.randomBytes生成3个字节并转换为hex
  2. 使用前5个字符转换为整数(最大值为fffff == 1048575> 999999
  3. 如果结果> 999999,请从步骤1重新开始

它将以某种方式创建递归函数。它在逻辑上是否正确,是否会引起性能问题?

6 个答案:

答案 0 :(得分:5)

有几种方法可以从随机位中提取一定范围内的随机数。 NIST Special Publication 800-90A revision 1: Recommendation for Random Number Generation Using Deterministic Random Bit Generators

中描述了一些常见的

尽管此标准是关于确定性随机位生成的,但是有一个有用的附录称为 A.5将随机位转换为随机数,它描述了三种有用的方法。

描述的方法是:

  • A.5.1简单丢弃方法
  • A.5.2复杂丢弃方法
  • A.5.3简单模块化方法

它们中的前两个不是确定性的,但生成的数字完全没有偏差。它们基于拒绝抽样。最后一个是时间常数和确定性的,但具有非零(但可以忽略)的偏差。不过,要实现可忽略的偏差,还需要相对大量的随机性。

您的算法显然是“简单丢弃方法”的一种版本,因此很好。


当然,您应该使用通用方法,该方法在给定N的情况下都是有效的。在这种情况下,应考虑在简单丢弃方法上考虑复杂丢弃方法或简单模块化方法。还有其他更复杂的算法甚至更有效,但是通常使用这两种方法都可以。

请注意,在生成N范围内的随机数时,首先检查[0, N)是否为2的幂通常是有益的。如果N 是2的幂,则无需使用这些可能昂贵的计算中的任何一个;只需使用随机位或字节生成器中所需的位即可。

答案 1 :(得分:4)

这是一种正确的算法(https://en.wikipedia.org/wiki/Rejection_sampling),尽管您可以考虑使用按位运算而不是转换为十六进制。如果随机数生成器发生故障,它可以永远运行-您可以考虑尝试固定次数,然后抛出异常而不是永远循环。

答案 2 :(得分:2)

主要的性能问题是,在某些平台上,crypto.randomBytes会在熵用尽时阻塞。因此,如果您要使用随机性,就不要浪费它。

因此,我将使用以下整数运算代替您的字符串比较。

if (random_bytes < 16700000) {
    return random_bytes = random_bytes - 100000 * Math.floor(random_bytes/100000);
}

从前3个字节中得出答案的机率大约为99.54%,而采用这种方法的几率约为76%。

答案 3 :(得分:0)

我建议采用以下方法:

private generateCode(): string {
    let code: string = "";

    do {
        code += randomBytes(3).readUIntBE(0, 3);
        // code += Number.parseInt(randomBytes(3).toString("hex"), 16);
    } while (code.length < 6);

    return code.slice(0, 6);
}

这将数字代码作为字符串返回,但是如果有必要将其作为数字来获取,则更改为return Number.parseInt(code.slice(0, 6))

答案 4 :(得分:-1)

我称其为random_6d算法。最坏的情况是只有一个附加循环。

var random_6d = function(n2){
    var n1 = crypto.randomBytes(3).readUIntLE(0, 3) >>> 4;

    if(n1 < 1000000)
        return n1;

    if(typeof n2 === 'undefined')
        return random_6d(n1);

    return Math.abs(n1 - n2);
};

循环版本:

var random_6d = function(){
    var n1, n2;

    while(true){
        n1 = crypto.randomBytes(3).readUIntLE(0, 3) >>> 4;

        if(n1 < 1000000)
            return n1;

        if(typeof n2 === 'undefined')
            n2 = n1;
        else
            return Math.abs(n1 - n2);
    };
};

答案 5 :(得分:-1)

这是使用holder.Rank.setText(String.valueOf(currentposition.getRank())); 函数的简单代码。

randomBytes()