这是一个密码安全的方法来生成一个随机数在节点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到除数: var random = integer / (0xffffffffffffffff+1); 编辑 :由于数字在尾数中没有8个字节的精度,所以无论math上小于1.0它都会舍入到1.0

该页面推测在ECMA标准的未来版本中,数字将以16字节浮点表示。 如果你想为此做准备,你可以使用16而不是8字节的随机性,除以0xffffffffffffffffffffffffffffffff

我会用几个警告的话来结束:对于密码应用程序来说,通过这个消息生成的随机数很可能是完全不安全的,因为对于很less的熵,只有不到64位的随机性。 通常oleksii是正确的与他的评论:不要发明,甚至实现自己的encryption。

不正确, integer的第一个数字肯定是有偏见的。 这不是一个从0到1(独占)创build十进制值的好方法。