Skip to content

Commit

Permalink
lib,src: make pseudoRandomBytes alias randomBytes
Browse files Browse the repository at this point in the history
Previously pseudoRandomBytes worked similarly to randomBytes but in the
event of insufficient entropy would silently return non-secure values.

As of f68a116, the entropy pool blocks if there is insufficient entropy
instead of giving an error so there is now no longer a case where
pseudoRandomBytes would act differently than randomBytes.

Docs are updated to remove pseudoRandomBytes and to clarify that
randomBytes now does block instead of erring when entropy is low.

PR-URL: #557
Reviewed-By: Ben Noordhuis <[email protected]>
Reviewed-By: Fedor Indutny <[email protected]>
  • Loading branch information
calvinmetcalf authored and bnoordhuis committed Jan 22, 2015
1 parent c6cd460 commit e5e5980
Show file tree
Hide file tree
Showing 3 changed files with 13 additions and 32 deletions.
14 changes: 4 additions & 10 deletions doc/api/crypto.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -647,16 +647,10 @@ Generates cryptographically strong pseudo-random data. Usage:
// most likely, entropy sources are drained
}

NOTE: Will throw error or invoke callback with error, if there is not enough
accumulated entropy to generate cryptographically strong data. In other words,
`crypto.randomBytes` without callback will not block even if all entropy sources
are drained.

## crypto.pseudoRandomBytes(size[, callback])

Identical to `crypto.randomBytes` except that, instead of throwing an error when
there is not enough accumulated entropy to generate cryptographically strong
data, it will silently return **non**-cryptographically strong data.
NOTE: This will block if there is insufficient entropy, although it should
normally never take longer than a few milliseconds. The only time when this
may conceivably block is right after boot, when the whole system is still
low on entropy.

## Class: Certificate

Expand Down
8 changes: 2 additions & 6 deletions lib/crypto.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ exports.DEFAULT_ENCODING = 'buffer';
try {
var binding = process.binding('crypto');
var randomBytes = binding.randomBytes;
var pseudoRandomBytes = binding.pseudoRandomBytes;
var getCiphers = binding.getCiphers;
var getHashes = binding.getHashes;
} catch (e) {
Expand Down Expand Up @@ -636,12 +635,9 @@ exports.setEngine = function setEngine(id, flags) {
return binding.setEngine(id, flags);
};

exports.randomBytes = randomBytes;
exports.pseudoRandomBytes = pseudoRandomBytes;

exports.rng = randomBytes;
exports.prng = pseudoRandomBytes;
exports.randomBytes = exports.pseudoRandomBytes = randomBytes;

exports.rng = exports.prng = randomBytes;

exports.getCiphers = function() {
return filterDuplicates(getCiphers.call(null, arguments));
Expand Down
23 changes: 7 additions & 16 deletions src/node_crypto.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4589,25 +4589,18 @@ class RandomBytesRequest : public AsyncWrap {
};


template <bool pseudoRandom>
void RandomBytesWork(uv_work_t* work_req) {
RandomBytesRequest* req =
ContainerOf(&RandomBytesRequest::work_req_, work_req);
int r;

// Ensure that OpenSSL's PRNG is properly seeded.
CheckEntropy();

if (pseudoRandom == true) {
r = RAND_pseudo_bytes(reinterpret_cast<unsigned char*>(req->data()),
req->size());
} else {
r = RAND_bytes(reinterpret_cast<unsigned char*>(req->data()), req->size());
}
const int r = RAND_bytes(reinterpret_cast<unsigned char*>(req->data()),
req->size());

// RAND_bytes() returns 0 on error. RAND_pseudo_bytes() returns 0 when the
// result is not cryptographically strong - but that's not an error.
if (r == 0 && pseudoRandom == false) {
// RAND_bytes() returns 0 on error.
if (r == 0) {
req->set_error(ERR_get_error());
} else if (r == -1) {
req->set_error(static_cast<unsigned long>(-1));
Expand Down Expand Up @@ -4650,7 +4643,6 @@ void RandomBytesAfter(uv_work_t* work_req, int status) {
}


template <bool pseudoRandom>
void RandomBytes(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);

Expand All @@ -4675,12 +4667,12 @@ void RandomBytes(const FunctionCallbackInfo<Value>& args) {
obj->Set(env->domain_string(), env->domain_array()->Get(0));
uv_queue_work(env->event_loop(),
req->work_req(),
RandomBytesWork<pseudoRandom>,
RandomBytesWork,
RandomBytesAfter);
args.GetReturnValue().Set(obj);
} else {
Local<Value> argv[2];
RandomBytesWork<pseudoRandom>(req->work_req());
RandomBytesWork(req->work_req());
RandomBytesCheck(req, argv);
delete req;

Expand Down Expand Up @@ -5041,8 +5033,7 @@ void InitCrypto(Handle<Object> target,
env->SetMethod(target, "setEngine", SetEngine);
#endif // !OPENSSL_NO_ENGINE
env->SetMethod(target, "PBKDF2", PBKDF2);
env->SetMethod(target, "randomBytes", RandomBytes<false>);
env->SetMethod(target, "pseudoRandomBytes", RandomBytes<true>);
env->SetMethod(target, "randomBytes", RandomBytes);
env->SetMethod(target, "getSSLCiphers", GetSSLCiphers);
env->SetMethod(target, "getCiphers", GetCiphers);
env->SetMethod(target, "getHashes", GetHashes);
Expand Down

1 comment on commit e5e5980

@jonathanong
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

Please sign in to comment.