src: seed V8's random number generator at startup
authorBen Noordhuis <info@bnoordhuis.nl>
Fri, 20 Sep 2013 20:01:49 +0000 (22:01 +0200)
committerFedor Indutny <fedor.indutny@gmail.com>
Wed, 26 Mar 2014 07:31:32 +0000 (11:31 +0400)
The default entropy source is /dev/urandom on UNIX platforms, which is
okay but we can do better by seeding it from OpenSSL's entropy pool.

On Windows we can certainly do better; on that platform, V8 seeds the
random number generator using only the current system time.

Fixes #6250.

NB: This is a back-port of commit 7ac2391 from the master branch that
for some reason never got back-ported to the v0.10 branch.

The default on UNIX platforms in v0.10 is different and arguably worse
than it is with master: if no entropy source is provided, V8 3.14 calls
srandom() with a xor of the PID and the current time in microseconds.

That means that on systems with a coarse system clock, the initial
state of the PRNG may be easily guessable.

The situation on Windows is even more dire because there the PRNG is
seeded with only the current time... in milliseconds.

src/node.cc
src/node_crypto.cc
src/node_crypto.h

index ac906f0..958c86d 100644 (file)
@@ -3057,6 +3057,12 @@ int Start(int argc, char *argv[]) {
   Init(argc, argv_copy);
 
   V8::Initialize();
+#if HAVE_OPENSSL
+  // V8 on Windows doesn't have a good source of entropy. Seed it from
+  // OpenSSL's pool.
+  V8::SetEntropySource(crypto::EntropySource);
+#endif
+
   {
     Locker locker;
     HandleScope handle_scope;
index e23f150..702a1d1 100644 (file)
@@ -157,6 +157,14 @@ Handle<Value> ThrowCryptoTypeError(unsigned long err) {
 }
 
 
+bool EntropySource(unsigned char* buffer, size_t length) {
+  // RAND_bytes() can return 0 to indicate that the entropy data is not truly
+  // random. That's okay, it's still better than V8's stock source of entropy,
+  // which is /dev/urandom on UNIX platforms and the current time on Windows.
+  return RAND_bytes(buffer, length) != -1;
+}
+
+
 void SecureContext::Initialize(Handle<Object> target) {
   HandleScope scope;
 
index e4c3cfb..2b16574 100644 (file)
@@ -280,6 +280,7 @@ class Connection : ObjectWrap {
   friend class SecureContext;
 };
 
+bool EntropySource(unsigned char* buffer, size_t length);
 void InitCrypto(v8::Handle<v8::Object> target);
 
 }  // namespace crypto