Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Node.js 节点:使用crypto.randomBytes生成6位随机数_Node.js_Algorithm_Cryptography - Fatal编程技术网

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

Node.js 节点:使用crypto.randomBytes生成6位随机数,node.js,algorithm,cryptography,Node.js,Algorithm,Cryptography,既然1000000不是2的幂,那么从0到999999随机生成精确值的正确方法是什么 这是我的方法: private generateCode(): string { let code: string = ""; do { code += randomBytes(3).readUIntBE(0, 3); // code += Number.parseInt(randomBytes(3).toString("hex"), 16); } whi

既然
1000000
不是2的幂,那么从
0
999999
随机生成精确值的正确方法是什么

这是我的方法:

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);
}
  • 使用
    crypto.randomBytes
    生成3个字节并转换为
    hex
  • 使用前5个字符转换为整数(最大值为
    fffff
    ==
    1048575
    99999
  • 如果结果>
    999999
    ,请再次从步骤1开始

  • 它将以某种方式创建一个递归函数。它是逻辑正确的,它会引起性能的关注吗?

    < P>这是一个正确的算法(),尽管您可以考虑使用位操作而不是转换为十六进制。如果随机数生成器出现故障,它可以永远运行——你可以考虑尝试一个固定的次数,然后抛出一个异常而不是循环循环。

    < P>主要的性能问题是,在一些平台上,<代码>密码。所以如果你使用它,你不想浪费任何随机性

    因此,我将使用以下整数操作来代替字符串比较

    if (random_bytes < 16700000) {
        return random_bytes = random_bytes - 100000 * Math.floor(random_bytes/100000);
    }
    
    if(随机字节<16700000){
    返回random\u bytes=random\u bytes-100000*数学地板(random\u bytes/100000);
    }
    

    这大约有99.54%的几率从前3个字节中生成答案,而您的方法的几率约为76%。

    有几种方法可以从随机位中提取一定范围内的随机数。中描述了一些常见的问题

    尽管本标准是关于确定性随机位生成的,但有一个名为a.5将随机位转换为随机数的有用附录,其中描述了三种有用的方法

    所述方法包括:

    • A.5.1简单丢弃方法
    • A.5.2复杂废弃方法
    • A.5.3简单模块化方法
    前两个参数在运行时间方面不是确定的,但生成的数值没有任何偏差。它们基于拒绝采样

    复数丢弃法讨论了一种在一定范围内生成大量随机数的更优方案。我认为它太复杂了,几乎无法正常使用;如果您需要额外的效率,我将研究下面描述的优化简单丢弃方法

    简单的模块化方法是时间常数和确定性的,但具有非零(但可以忽略不计)偏差。它需要相对大量的额外随机性来实现可忽略的偏差;基本上,要使偏差为2^128中的一个,需要在所需范围的位大小上加128位。对于较小的数字,这可能不是选择的方法

    您的算法显然是简单丢弃方法的一个版本(通常称为“拒绝采样”),因此它很好。


    我自己也想到了一种基于简单丢弃方法的非常有效的算法,称为“BC”代表“二进制比较”。这是基于这样的观察:比较只关注最高有效位,这意味着最低有效位仍应被视为随机的,因此可以重用。请注意,该方法尚未经过正式同行评审;我确实用简单的丢弃方法给出了一个非正式的等价性证明


    当然,如果给定
    N
    的任何值,您应该使用有效的通用方法。在这种情况下,应将复杂丢弃方法或简单模块化方法置于简单丢弃方法之上。还有其他更复杂的算法更有效,但通常使用这两种算法中的任何一种都可以


    注意,当在范围
    [0,N)
    。如果
    N
    是二的幂,则无需使用这些可能昂贵的计算;只需使用随机位或字节生成器中所需的位。

    我建议以下方法:

    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);
    }
    
    private generateCode():字符串{
    let代码:string=“”;
    做{
    code+=randomBytes(3)。readUIntBE(0,3);
    //code+=Number.parseInt(随机字节(3).toString(“十六进制”),16);
    }而(代码长度<6);
    返回码.切片(0,6);
    }
    

    这将以字符串形式返回数字代码,但如果需要将其作为数字,则将其更改为
    返回number.parseInt(code.slice(0,6))

    我将其称为
    随机算法。最坏情况下,只需一个附加循环

    var random_6d=函数(n2){
    var n1=加密随机字节(3).readUIntLE(0,3)>>>4;
    如果(n1<1000000)
    返回n1;
    如果(类型n2==‘未定义’)
    返回随机_6d(n1);
    返回数学绝对值(n1-n2);
    };
    
    循环版本:

    var random_6d=函数(){
    变种n1,n2;
    while(true){
    n1=加密随机字节(3).readUIntLE(0,3)>>>4;
    如果(n1<1000000)
    返回n1;
    如果(类型n2==‘未定义’)
    n2=n1;
    其他的
    返回数学绝对值(n1-n2);
    };
    };
    
    Math.floor(Math.random(1000000)*1000000)我知道,但是
    Math.random
    不是加密安全的。我的问题是使用
    crypto.randomBytes
    你可以计算出分数
    YourRandInt/maxmaxpability
    并将其与你想要的范围相乘(999.999),然后四舍五入到下一个整数。我不确定这是否会更频繁地产生某些数字。@TobiasK,谢谢,但是我认为这种方法与使用模运算的YourRandInt%1000000相同,使用模运算有x2的机会得到0到48575之间的值,我认为使用这种方法确实不会发生这种情况,因为每个
    Yo