lib,src: make pseudoRandomBytes alias randomBytes

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: https://github.com/iojs/io.js/pull/557
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: Fedor Indutny <fedor@indutny.com>
This commit is contained in:
Calvin Metcalf 2015-01-21 21:30:27 -05:00 committed by Ben Noordhuis
parent c6cd46041c
commit e5e598060e
3 changed files with 13 additions and 32 deletions

View File

@ -647,16 +647,10 @@ Generates cryptographically strong pseudo-random data. Usage:
// most likely, entropy sources are drained // most likely, entropy sources are drained
} }
NOTE: Will throw error or invoke callback with error, if there is not enough NOTE: This will block if there is insufficient entropy, although it should
accumulated entropy to generate cryptographically strong data. In other words, normally never take longer than a few milliseconds. The only time when this
`crypto.randomBytes` without callback will not block even if all entropy sources may conceivably block is right after boot, when the whole system is still
are drained. low on entropy.
## 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.
## Class: Certificate ## Class: Certificate

View File

@ -8,7 +8,6 @@ exports.DEFAULT_ENCODING = 'buffer';
try { try {
var binding = process.binding('crypto'); var binding = process.binding('crypto');
var randomBytes = binding.randomBytes; var randomBytes = binding.randomBytes;
var pseudoRandomBytes = binding.pseudoRandomBytes;
var getCiphers = binding.getCiphers; var getCiphers = binding.getCiphers;
var getHashes = binding.getHashes; var getHashes = binding.getHashes;
} catch (e) { } catch (e) {
@ -636,12 +635,9 @@ exports.setEngine = function setEngine(id, flags) {
return binding.setEngine(id, flags); return binding.setEngine(id, flags);
}; };
exports.randomBytes = randomBytes; exports.randomBytes = exports.pseudoRandomBytes = randomBytes;
exports.pseudoRandomBytes = pseudoRandomBytes;
exports.rng = randomBytes;
exports.prng = pseudoRandomBytes;
exports.rng = exports.prng = randomBytes;
exports.getCiphers = function() { exports.getCiphers = function() {
return filterDuplicates(getCiphers.call(null, arguments)); return filterDuplicates(getCiphers.call(null, arguments));

View File

@ -4589,25 +4589,18 @@ class RandomBytesRequest : public AsyncWrap {
}; };
template <bool pseudoRandom>
void RandomBytesWork(uv_work_t* work_req) { void RandomBytesWork(uv_work_t* work_req) {
RandomBytesRequest* req = RandomBytesRequest* req =
ContainerOf(&RandomBytesRequest::work_req_, work_req); ContainerOf(&RandomBytesRequest::work_req_, work_req);
int r;
// Ensure that OpenSSL's PRNG is properly seeded. // Ensure that OpenSSL's PRNG is properly seeded.
CheckEntropy(); CheckEntropy();
if (pseudoRandom == true) { const int r = RAND_bytes(reinterpret_cast<unsigned char*>(req->data()),
r = RAND_pseudo_bytes(reinterpret_cast<unsigned char*>(req->data()), req->size());
req->size());
} else {
r = RAND_bytes(reinterpret_cast<unsigned char*>(req->data()), req->size());
}
// RAND_bytes() returns 0 on error. RAND_pseudo_bytes() returns 0 when the // RAND_bytes() returns 0 on error.
// result is not cryptographically strong - but that's not an error. if (r == 0) {
if (r == 0 && pseudoRandom == false) {
req->set_error(ERR_get_error()); req->set_error(ERR_get_error());
} else if (r == -1) { } else if (r == -1) {
req->set_error(static_cast<unsigned long>(-1)); req->set_error(static_cast<unsigned long>(-1));
@ -4650,7 +4643,6 @@ void RandomBytesAfter(uv_work_t* work_req, int status) {
} }
template <bool pseudoRandom>
void RandomBytes(const FunctionCallbackInfo<Value>& args) { void RandomBytes(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args); Environment* env = Environment::GetCurrent(args);
@ -4675,12 +4667,12 @@ void RandomBytes(const FunctionCallbackInfo<Value>& args) {
obj->Set(env->domain_string(), env->domain_array()->Get(0)); obj->Set(env->domain_string(), env->domain_array()->Get(0));
uv_queue_work(env->event_loop(), uv_queue_work(env->event_loop(),
req->work_req(), req->work_req(),
RandomBytesWork<pseudoRandom>, RandomBytesWork,
RandomBytesAfter); RandomBytesAfter);
args.GetReturnValue().Set(obj); args.GetReturnValue().Set(obj);
} else { } else {
Local<Value> argv[2]; Local<Value> argv[2];
RandomBytesWork<pseudoRandom>(req->work_req()); RandomBytesWork(req->work_req());
RandomBytesCheck(req, argv); RandomBytesCheck(req, argv);
delete req; delete req;
@ -5041,8 +5033,7 @@ void InitCrypto(Handle<Object> target,
env->SetMethod(target, "setEngine", SetEngine); env->SetMethod(target, "setEngine", SetEngine);
#endif // !OPENSSL_NO_ENGINE #endif // !OPENSSL_NO_ENGINE
env->SetMethod(target, "PBKDF2", PBKDF2); env->SetMethod(target, "PBKDF2", PBKDF2);
env->SetMethod(target, "randomBytes", RandomBytes<false>); env->SetMethod(target, "randomBytes", RandomBytes);
env->SetMethod(target, "pseudoRandomBytes", RandomBytes<true>);
env->SetMethod(target, "getSSLCiphers", GetSSLCiphers); env->SetMethod(target, "getSSLCiphers", GetSSLCiphers);
env->SetMethod(target, "getCiphers", GetCiphers); env->SetMethod(target, "getCiphers", GetCiphers);
env->SetMethod(target, "getHashes", GetHashes); env->SetMethod(target, "getHashes", GetHashes);