使用加密库,我可以要求该库给我一些随机字节。问题是这个字节是每个从 0 到 255(包括)的数字,因此创建均匀分布的结果并不是那么简单。
我的意思是:
该函数接收一个数字 N,即 10, 100, ... 10^b,其中 b 是一个介于 1 和 8 之间的数字(可以更大,但我不需要更大的数字)并返回一个介于 0 和给定的数字(不包括给定的数字),比如说如果 N 是 100,函数的结果是从 0 到 99,如果 N 是 10,结果是从 0 到 9。
您可以使用 Math.random 创建一个随机数,然后乘以 N,然后使用 floor。但是,Math.random 在密码学上不是安全的,因此必须使用随机生成的 2^8m 的数字来完成,其中 m 是赋予 crypto.randomBytes 的任意字节数。
我创建了一个简单的函数,显然它正在工作。但是,我知道在随机数中引入一些偏差是相当容易的,我只想对其进行验证,因为它对项目有些重要。
genera_aleatorio_residuo_potencia10 : function (n, cb) {
var digitos = Math.log(n) / Math.LN10;
var extra_base2 = digitos > 8 ? digitos - 8 : 0;
if (Math.floor(digitos + .4) - digitos > 0.00000001) {
return cb("Numero no es potencia de 10 (10, 100, 1000...)", null);
}
digitos = Math.round(digitos);
async.parallel({
r1 : crypto_helper.generador_random_bytes(1),
r2 : crypto_helper.generador_random_bytes(1)
}, function (err, res) {
if (err) {
return cb(err, null);
}
var r1 = res.r1[0] + 1;
var r2 = res.r2[0] + 1;
var aleatorio = (Math.pow(5, digitos) - 1) * Math.pow(2, extra_base2) * r1 + r2;
cb(null, aleatorio % n);
});
}
不用说:crypto_helper.generador_random_bytes 是 node.js 的 crypto.randomBytes 的包装器,我经常使用它来使其与异步库更友好。
我使用 Math.pow(5, digitos) 和 Math.pow(2, extra_base2) 的理由是 N 和 256 之间的最小公倍数。实际上,n 永远不会大于 100000000,所以 Math.pow( 2, extra_base2) 不应该在我们的产品中使用,但我仍然想确保它对其他人有意义。