简体   繁体   中英

Node.js Secure Random Float from Crypto Buffer

Not for any practical purpose, of course, but I tried to generate a secure random floating point number using the Node's crypto module. Essentially, the following:

var crypto = require('crypto');
var buf = crypto.randomBytes(4);
var float = buf.readFloatBE();

This doesn't work, as far as the following test can tell, in an average of 0.40% of cases. Instead of getting a float, I get NaN .

var colors = require('colors');
var crypto = require('crypto');

var buf = new Buffer(4);
var fails = 0, tries = 100000;
var failures = [];

for (var i = 0; i < tries; i++) {
    var num = crypto.randomBytes(4).readFloatBE(0);
    try {
        buf.writeFloatBE(num, 0);
    } catch (e) {
        fails++;
        failures.push(buf.readUInt32BE(0).toString(2));
    }
}

var percent = 100 * fails / tries;
if (fails)
    percent = (percent.toFixed(2) + "%").red;
else
    percent = '0.00%'.blue.bold;
console.log('Test ' + 'complete'.green.bold + ', ' + percent + ": " + fails + " / " + tries);
fails && console.log('Failed'.red + ' values:', failures.join(', '));

I'm guessing this is due to the IEEE single precision floating point number specification, but I'm not familiar with exactly how the float is stored as binary.

Why does this happen, exactly, and apart from simply generating floats until I get a valid number, how can I circumvent this?

EDIT : when looking at the filtered binary data, it appears they all follow the same pattern: the first 8 bits are all set. Everything else is random.

从当前版本的节点可以明显看出, 缓冲库的源代码在906行中指定noAssert还检查以查看提供的Number是否不是NaN ,因此简单地指定noAssert写入InfinityNaN-Infinity缓冲区的-Infinity大。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM