用node.js生成10的幂模数的密码随机数

使用encryption库,我可以要求库给我一些随机字节。 问题是这个字节是从0到255每个(包含)的数字,因此创build一个均匀分布的结果并不那么简单。

我的意思是以下几点:

函数接收到的数字N为10,100,… 10 ^ b,其中b是1到8之间的数字(可以更大,但是我不需要更大的数字),并返回0和给定的数字(不包括给定的数字),所以说,如果N是100,则函数的结果是从0到99,如果N是10,则结果是从0到9。

您可以使用Math.random创build一个随机数,然后乘以N,然后使用floor。 但是,Math.random不是密码安全的,所以必须使用随机生成的2 ^ 8m的数字来完成,其中m只是给予crypto.randomBytes的任意数量的字节。

我创build了一个显然正在工作的简单函数。 不过,我知道把随机数的一些偏差引入是相当容易的,我只希望对它进行validation,因为这对项目来说有些重要。

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的包装,我经常用它来使它与async库友好。

我使用Math.pow(5,digitos)和Math.pow(2,extra_base2)的推理是N和256之间的最小公倍数。在实践中,n永远不会大于100000000,所以Math.pow 2,extra_base2)不应该在我们的产品中使用,但我仍然希望确保它对其他人有意义。

我简单地模仿了Java的SecureRandom.nextInt(int)在这里做了什么,我find了一个很好的解决scheme: SecureRandom.nextInt(int)将尽快发布代码(我现在很忙)。 我打算使用我开发的代码,因为我确认提出的解决scheme有偏见(根本不可接受)。

这里是JDK代码的改编。 注意31位数字的限制,因为我意识到JS在32位补码上完成了所有的位操作。 我没有实现2号码的特殊情况,因为我不会使用它。 解决scheme是一般的数字,不只是10的权力…我敢肯定,基数为10的数字必须有一个更好的解决scheme,但无论如何。 我重写了代码,不使用我的库,并用英文编写,以便其他人可以更容易地使用它。

 var crypto_random_number_range = function (n, cb) { //result is a number from 0 a n-1 //Javascript works with 32 bits for bitwise operations but these are signed (2-complement), so it is good to limit the size of n if (n <= 0 || n > 2147483647) { return cb("n must be larger than 0 and smaller than 2147483647", null); } var bits, val; async.doWhilst( function (cb2) { crypto.randomBytes(4, function (err, rbytes) { if (err) { return cb2(err); } bits = ((rbytes[3] & 0x7f) << 24) + (rbytes[2] << 16) + (rbytes[1] << 8) + rbytes[0]; val = bits % n; cb2(); }); }, function () { return (bits - val + (n-1)) < 0; }, function (err) { if (err) { return cb(err, null); } return cb(null, val); } ); } 

做了几个testing,似乎工作得很好。

 var kazutsukuru = function kazutsukuru(kaketeiruno, kotae) { crypto.randomBytes(4, function(mondai, baito) { if (mondai) { return kotae(mondai); } kotae(null, Math.floor(baito.readUInt32BE(0) / 4294967296 * kaketeiruno)); }); }; 

这应该做你想要的。 我决定让我的答案难以阅读,因为你的问题很难阅读。