randomBytes vs pseudoRandomBytes

2019-03-17 09:18发布

问题:

In what situations is it acceptable (from a security standpoint) to use node's crypto.pseudoRandomBytes instead of the cryptographically-strong crypto.randomBytes?

I assume pseudoRandomBytes performs better at the expense of being more predictable (incorrect), but the docs don't really have much to say about how less-strong it is.

Specifically, I'm wondering if I'm ok using pseudoRandomBytes to generate a CSRF token.

回答1:

As it turns out, with the default OpenSSL (which is bundled with node, but if you've built your own, it is possible to configure different engines), the algorithm to generate random data is exactly the same for both randomBytes (RAND_bytes) and pseudoRandomBytes (RAND_pseudo_bytes).

The one and only difference between the two calls depends on the version of node you're using:

  • In node v0.12 and prior, randomBytes returns an error if the entropy pool has not yet been seeded with enough data. pseudoRandomBytes will always return bytes, even if the entropy pool has not been properly seeded.
  • In node v4 and later, randomBytes does not return until the entropy pool has enough data. This should take only a few milliseconds (unless the system has just booted).

Once the the entropy pool has been seeded with enough data, it will never "run out," so there is absolutely no effective difference between randomBytes and pseudoRandomBytes once the entropy pool is full.

Because the exact same algorithm is used to generate randrom data, there is no difference in performance between the two calls (one-time entropy pool seeding notwithstanding).



回答2:

Just a clarification, both have the same performance:

var crypto = require ("crypto")
var speedy = require ("speedy");

speedy.run ({
    randomBytes: function (cb){
        crypto.randomBytes (256, cb);
    },
    pseudoRandomBytes: function (cb){
        crypto.pseudoRandomBytes (256, cb);
    }
});

/*
File: t.js

Node v0.10.25
V8 v3.14.5.9
Speedy v0.1.1

Tests: 2
Timeout: 1000ms (1s 0ms)
Samples: 3
Total time per test: ~3000ms (3s 0ms)
Total time: ~6000ms (6s 0ms)

Higher is better (ops/sec)

randomBytes
  58,836 ± 0.4%
pseudoRandomBytes
  58,533 ± 0.8%

Elapsed time: 6318ms (6s 318ms)
*/


回答3:

If it's anything like the standard PRNG implementations in other languages, it is probably either not seeded by default or it is seeded by a simple value, like a timestamp. Regardless, the seed is possibly very easily guessable.