JS中生成一个随机数吗

JS中生成一个随机数吗

本文介绍了这是一个加密的安全方法在Node JS中生成一个随机数吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这里是我用自己的Cryptography.random()替换Math.random()的尝试。我的代码生成一个加密安全的随机数,你看到任何优化机会吗?

Here's my attempt to replace Math.random() with my own Cryptography.random(). Will my code generate a cryptographically secure random number and do you see any opportunities for optimization?

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;
        });
    });
});


推荐答案

所以你想要实现的是生成一个随机在正确的加密库安全生成的4个字节中的0和1之间浮动?



将产生偏差,因为您的整数在集合{0,1,...,4294967295}中是均匀分布的。例如范围的联合

So what you are trying to achieve is generating a random float between 0 and 1 out of 4 bytes that have been securely generated by a proper crypto library?

The way you do it in your question will generate a bias as your integer is uniformly distributed amongst the set {0,1,…,4294967295}. For example the union of the ranges

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

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

that generates a leading 1 as the first decimal digit is about ten times larger than the range that generates a leading 9:

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

integer

而是可以将 integer 除以其最大的可能值, code> 0xffffffff 。因为javascript使用8字节浮点值为其数字类型4字节值不能给你足够的范围,虽然。为了安全起见,您可以改为读取8个字节(由于用于存储指数的位,因此需要多一点):

Instead you can divide integer by its largest possible value which would be 0xffffffff. As javascript uses 8 byte floating point values for its number types 4 byte values don't give you enough range, though. To be on the safe side you can instead read 8 bytes (which is a little bit more than necessary because of the bits used to store the exponent):

//…
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包括在该范围内)。 :由于数字在尾数中没有8个字节的精度,因此无论小于 1.0 ,都会舍入到 1.0 code>数学。

The above generates numbers in the interval [0.0,1.0] (both 0.0 and 1.0 are included in the range). Edit: As the number does not have 8 byte precision in the mantissa it will get rounded to 1.0 regardless of being less than 1.0 mathematically.

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

This page speculates that numbers will be represented by 16byte floating point in future revisions of the ECMA standard. If you want to prepare for that you can use 16 instead of 8 bytes randomness and divide by 0xffffffffffffffffffffffffffffffff

结束语有几个警告:对于加密应用程序,您通过此消息生成的随机数可能是完全不安全的,因为随着少于64位的随机性,你有远至少熵。一般来说,oleksii是正确的他的评论:不要发明,甚至实现你自己的加密。

I'll conclude with a few words of warning: For cryptographic applications the random number you generate via this message are likely to be completely insecure as with less than 64bit of randomness you have by far to few entropy. And generally oleksii is right with his comment: Don't invent or even implement your own crypto.

这篇关于这是一个加密的安全方法在Node JS中生成一个随机数吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-23 14:38