【问题标题】:Is this a cryptographically secure method to generate a random number in Node JS?这是在 Node JS 中生成随机数的加密安全方法吗?
【发布时间】:2014-05-06 21:45:18
【问题描述】:

这是我用我自己的Cryptography.random() 替换Math.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;
        });
    });
});

【问题讨论】:

  • 我不熟悉node.js,但是"with my own Cryptography.random()"是一个危险信号,here is why

标签: node.js random cryptography


【解决方案1】:

那么您想要实现的是在 适当的加密库安全生成的 4 个字节中生成一个介于 0 和 1 之间的随机浮点数?

您在问题中的处理方式会产生偏差,因为您的 integer 均匀分布在集合 {0,1,...,4294967295} 中。例如范围的并集

{10000000000,…,19999999999},
{1000000000,…,1999999999}
{100000000,…,199999999}
{10000000,…,19999999}
{1000000,…,1999999} 
…
{10,…,19}
{1}

生成前导 1 作为第一个十进制数字的范围大约是生成前导 9 的范围的十倍:

{9000000000,…,9999999999}
{900000000,…,999999999}
{90000000,…,99999999}
{9000000,…,9999999} 
…
{90,…,99}
{9}

integer 的可能值中没有前导 9 的 11 位数字。)

相反,您可以将integer 除以其最大可能值0xffffffff。由于 javascript 对其数字类型使用 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 字节精度,因此会四舍五入到1.0,无论数学上小于1.0

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

我将以几句警告作为结尾:对于加密应用程序,您通过此消息生成的随机数很可能是完全不安全的,因为您的随机性小于 64 位,因此您的熵几乎没有。通常 oleksii 的评论是正确的:不要发明甚至实施自己的加密货币。

【讨论】:

  • 我是第一个 - 虽然答案略短:)
  • @owlstead,两者都只差一点点;)
  • 谢谢!非常感谢您的回答!
  • 嗨 Perseids,是否可以通过更改我上面的函数来生成 64 位随机性?我只需要调整一些值吗?
  • @Kirk:我不明白你在问什么。我在回答中提出的调整已经生成了 64 位随机浮点数。你缺少什么功能?
【解决方案2】:

不正确,integer 的前几位肯定有偏差。这不是创建从 0 到 1(不包括)的十进制值的好方法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-06-08
    • 1970-01-01
    • 1970-01-01
    • 2016-06-23
    • 2015-09-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多