如何使用crypto.randomBytes在特定范围内生成随机数?
我希望能够生成这样的随机数:
console.log(random(55, 956)); // where 55 is minimum and 956 is maximum我被限制使用crypto.randomBytes只在随机函数中生成这个范围内的随机数。
我知道如何将生成的字节从randomBytes转换为十六进制或十进制,但我不知道如何从数学上从随机字节得到特定范围内的随机数。
发布于 2015-11-10 10:01:01
感谢@Mustafamg的回答和@CodesInChaos的巨大帮助,我设法解决了这个问题。我做了一些调整,增加幅度最大256^6-1或281,474,976,710,655.范围可以增加更多,但您需要为大整数使用额外的库,因为256^7-1超出了Number.MAX_SAFE_INTEGER限制。
如果有人有同样的问题,可以随意使用。
var crypto = require('crypto');
/*
Generating random numbers in specific range using crypto.randomBytes from crypto library
Maximum available range is 281474976710655 or 256^6-1
Maximum number for range must be equal or less than Number.MAX_SAFE_INTEGER (usually 9007199254740991)
Usage examples:
cryptoRandomNumber(0, 350);
cryptoRandomNumber(556, 1250425);
cryptoRandomNumber(0, 281474976710655);
cryptoRandomNumber((Number.MAX_SAFE_INTEGER-281474976710655), Number.MAX_SAFE_INTEGER);
Tested and working on 64bit Windows and Unix operation systems.
*/
function cryptoRandomNumber(minimum, maximum){
var distance = maximum-minimum;
if(minimum>=maximum){
console.log('Minimum number should be less than maximum');
return false;
} else if(distance>281474976710655){
console.log('You can not get all possible random numbers if range is greater than 256^6-1');
return false;
} else if(maximum>Number.MAX_SAFE_INTEGER){
console.log('Maximum number should be safe integer limit');
return false;
} else {
var maxBytes = 6;
var maxDec = 281474976710656;
// To avoid huge mathematical operations and increase function performance for small ranges, you can uncomment following script
/*
if(distance<256){
maxBytes = 1;
maxDec = 256;
} else if(distance<65536){
maxBytes = 2;
maxDec = 65536;
} else if(distance<16777216){
maxBytes = 3;
maxDec = 16777216;
} else if(distance<4294967296){
maxBytes = 4;
maxDec = 4294967296;
} else if(distance<1099511627776){
maxBytes = 4;
maxDec = 1099511627776;
}
*/
var randbytes = parseInt(crypto.randomBytes(maxBytes).toString('hex'), 16);
var result = Math.floor(randbytes/maxDec*(maximum-minimum+1)+minimum);
if(result>maximum){
result = maximum;
}
return result;
}
}
到目前为止,它运行良好,您可以使用它作为非常好的随机数生成器,但我严格地不建议在任何加密服务中使用该函数。如果你愿意的话,你可以冒险使用它。
欢迎所有的评论,建议和批评!
发布于 2015-11-09 13:22:10
要在一定范围内生成随机数,可以使用以下公式
Math.random() * (high - low) + low但是您希望使用crypto.randomBytes而不是Math.random(),这个函数返回一个带有随机生成字节的缓冲区。反过来,您需要将此函数的结果从字节转换为十进制。这可以使用biguint格式的包来完成。要安装此软件包,只需使用以下命令:
npm install biguint-format --save现在您需要将crypto.randomBytes的结果转换为十进制,您可以这样做:
var x= crypto.randomBytes(1);
return format(x, 'dec');现在您可以创建随机函数,如下所示:
var crypto = require('crypto'),
format = require('biguint-format');
function randomC (qty) {
var x= crypto.randomBytes(qty);
return format(x, 'dec');
}
function random (low, high) {
return randomC(4)/Math.pow(2,4*8-1) * (high - low) + low;
}
console.log(random(50,1000));发布于 2015-11-09 13:09:05
以生成范围在55 .956,首先在0范围内生成一个随机数。901,其中901 =956-55。然后把55加到你刚刚生成的数字上。
在0范围内生成一个数字。901,选择两个随机字节并屏蔽6位。这会给你一个在0范围内的10位随机数。1023.如果这个数字是<= 901,那么您就完成了。如果它大于901,则丢弃它,再得到两个随机字节。不要试图使用MOD,使数字进入正确的范围,这将扭曲输出,使其非随机。
ETA:减少不得不丢弃生成的数字的机会。
因为我们从RNG中取了两个字节,所以我们得到了0范围内的一个数字..65535。现在65535 MOD 902是591。因此,如果我们的两个字节随机数小于(65535 - 591),即小于64944,我们可以安全地使用MOD运算符,因为每个数字在0范围内。901现在也同样有可能。任何两个字节的数字>= 64944仍然必须被丢弃,因为使用它会使输出偏离随机。以前,不得不拒绝一个数字的机会是(1024-901)/ 1024 = 12%。现在被拒绝的几率是(65535 - 64944) / 65535 = 1%。我们不太可能拒绝随机生成的数字。
running <- true
while running
num <- two byte random
if (num < 64944)
result <- num MOD 902
running <- false
endif
endwhile
return result + 55https://stackoverflow.com/questions/33609404
复制相似问题