这是一个密码安全的方法来生成一个随机数在节点JS?
这是我用我自己的Cryptography.random()replaceMath.random()的尝试。 我的代码是否会生成一个密码安全的随机数,您是否看到有优化的机会?
NodeCrypto = require('crypto'); Cryptography = function() { } Cryptography.random = Promise.method(function() { return new Promise(function(resolve, reject) { NodeCrypto.randomBytes(4, function(ex, buffer) { var hex = buffer.toString('hex'); var integer = parseInt(hex, 16); var random = Number('0.'+integer); resolve(random); return random; }); }); });
那么你试图实现的是在一个合适的encryption库安全地生成的4个字节中,从0到1之间生成一个随机数。
在你的问题中,你这样做会产生一个偏见,因为你的integer
在集合{0,1,…,4294967295}之间是均匀分布的。 例如范围的联合
{10000000000,…,19999999999}, {1000000000,…,1999999999} {100000000,…,199999999} {10000000,…,19999999} {1000000,…,1999999} … {10,…,19} {1}
生成前导1作为第一个十进制数字比生成前导9的范围大10倍左右:
{9000000000,…,9999999999} {900000000,…,999999999} {90000000,…,99999999} {9000000,…,9999999} … {90,…,99} {9}
( integer
的可能值中没有十位数字,前9位)
相反,您可以将integer
除以其最大可能值,即0xffffffff
。 由于javascript为其数字types使用了8字节的浮点值,但是4字节值并不能提供足够的范围。 为了安全起见,您可以读取8个字节(由于用于存储指数的位,这比需要的多一点):
//… NodeCrypto.randomBytes(8, function(ex, buffer) { var hex = buffer.toString('hex'); var integer = parseInt(hex, 16); var random = integer / 0xffffffffffffffff; resolve(random); return random; }); //…
以上生成区间[0.0,1.0]中的数字(范围中包括0.0和1.0)。 如果你想排除1.0,你可以加1到除数: 编辑 :由于数字在尾数中没有8个字节的精度,所以无论math上小于var random = integer / (0xffffffffffffffff+1);
1.0
它都会舍入到1.0
。
该页面推测在ECMA标准的未来版本中,数字将以16字节浮点表示。 如果你想为此做准备,你可以使用16而不是8字节的随机性,除以0xffffffffffffffffffffffffffffffff
我会用几个警告的话来结束:对于密码应用程序来说,通过这个消息生成的随机数很可能是完全不安全的,因为对于很less的熵,只有不到64位的随机性。 通常oleksii是正确的与他的评论:不要发明,甚至实现自己的encryption。
不正确, integer
的第一个数字肯定是有偏见的。 这不是一个从0到1(独占)创build十进制值的好方法。