diff --git a/bitcore.js b/bitcore.js
index aa0de4b..13f7293 100644
--- a/bitcore.js
+++ b/bitcore.js
@@ -20,6 +20,7 @@ requireWhenAccessed('const', './const');
requireWhenAccessed('Deserialize', './lib/Deserialize');
requireWhenAccessed('log', './util/log');
requireWhenAccessed('networks', './networks');
+requireWhenAccessed('SecureRandom', './lib/SecureRandom');
requireWhenAccessed('util', './util/util');
requireWhenAccessed('EncodedData', './util/EncodedData');
requireWhenAccessed('VersionedData', './util/VersionedData');
diff --git a/browser/build.js b/browser/build.js
index 05f7a62..38f97e4 100644
--- a/browser/build.js
+++ b/browser/build.js
@@ -42,6 +42,7 @@ var modules = [
'lib/SINKey',
'lib/Script',
'lib/ScriptInterpreter',
+ 'lib/SecureRandom',
'lib/Sign',
'lib/Transaction',
'lib/TransactionBuilder',
diff --git a/lib/BIP32.js b/lib/BIP32.js
index 94a7602..e1f8bfd 100644
--- a/lib/BIP32.js
+++ b/lib/BIP32.js
@@ -3,6 +3,7 @@ var base58 = imports.base58 || require('base58-native').base58;
var coinUtil = imports.coinUtil || require('../util');
var Key = imports.Key || require('./Key');
var Point = imports.Point || require('./Point');
+var SecureRandom = imports.SecureRandom || require('./SecureRandom');
var bignum = imports.bignum || require('bignum');
var crypto = require('crypto');
var networks = require('../networks');
@@ -27,7 +28,7 @@ var BIP32 = function(bytes) {
this.depth = 0x00;
this.parentFingerprint = new Buffer([0, 0, 0, 0]);
this.childIndex = new Buffer([0, 0, 0, 0]);
- this.chainCode = Key.generateSync().private;
+ this.chainCode = SecureRandom.getRandomBuffer(32);
this.eckey = Key.generateSync();
this.hasPrivateKey = true;
this.pubKeyHash = coinUtil.sha256ripe160(this.eckey.public);
diff --git a/lib/Connection.js b/lib/Connection.js
index f03e953..4b40d16 100644
--- a/lib/Connection.js
+++ b/lib/Connection.js
@@ -17,7 +17,8 @@ var util = imports.util || require('../util');
var Parser = imports.Parser || require('../util/BinaryParser');
var buffertools = imports.buffertools || require('buffertools');
var doubleSha256 = imports.doubleSha256 || util.twoSha256;
-var nonce = util.generateNonce();
+var SecureRandom = imports.SecureRandom || require('./SecureRandom');
+var nonce = function() {return SecureRandom.getPseudoRandomBuffer(8)};
var BIP0031_VERSION = 60000;
diff --git a/lib/SecureRandom.js b/lib/SecureRandom.js
new file mode 100644
index 0000000..fa7f5ef
--- /dev/null
+++ b/lib/SecureRandom.js
@@ -0,0 +1,5 @@
+if (process.versions) {
+ module.exports = require('./node/SecureRandom');
+ return;
+}
+module.exports = require('./browser/SecureRandom');
diff --git a/lib/browser/SecureRandom.js b/lib/browser/SecureRandom.js
new file mode 100644
index 0000000..79f1db5
--- /dev/null
+++ b/lib/browser/SecureRandom.js
@@ -0,0 +1,23 @@
+var imports = require('soop');
+
+var SecureRandom = require('../common/SecureRandom');
+
+SecureRandom.getRandomBuffer = function(size) {
+ if (!window.crypto && !window.msCrypto)
+ throw new Error('window.crypto not available');
+
+ if (window.crypto && window.crypto.getRandomValues)
+ var crypto = window.crypto;
+ else if (window.msCrypto && window.msCrypto.getRandomValues) //internet explorer
+ var crypto = window.msCrypto;
+ else
+ throw new Error('window.crypto.getRandomValues not available');
+
+ var bbuf = new Uint8Array(size);
+ crypto.getRandomValues(bbuf);
+ var buf = new Buffer(bbuf);
+
+ return buf;
+};
+
+module.exports = require('soop')(SecureRandom);
diff --git a/lib/common/SecureRandom.js b/lib/common/SecureRandom.js
new file mode 100644
index 0000000..a276d22
--- /dev/null
+++ b/lib/common/SecureRandom.js
@@ -0,0 +1,28 @@
+var imports = require('soop');
+
+var SecureRandom = function() {
+};
+
+/* secure random bytes that sometimes throws an error due to lack of entropy */
+SecureRandom.getRandomBuffer = function() {};
+
+/* insecure random bytes, but it never fails */
+SecureRandom.getPseudoRandomBuffer = function(size) {
+ var b32 = 0x100000000;
+ var b = new Buffer(size);
+
+ for (var i = 0; i <= size; i++) {
+ var j = Math.floor(i / 4);
+ var k = i - j * 4;
+ if (k == 0) {
+ r = Math.random() * b32;
+ b[i] = r & 0xff;
+ } else {
+ b[i] = (r = r >>> 8) & 0xff;
+ }
+ }
+
+ return b;
+};
+
+module.exports = require('soop')(SecureRandom);
diff --git a/lib/node/SecureRandom.js b/lib/node/SecureRandom.js
new file mode 100644
index 0000000..3639f75
--- /dev/null
+++ b/lib/node/SecureRandom.js
@@ -0,0 +1,10 @@
+var imports = require('soop');
+var crypto = imports.crypto || require('crypto');
+
+var SecureRandom = require('../common/SecureRandom');
+
+SecureRandom.getRandomBuffer = function(size) {
+ return crypto.randomBytes(size);
+}
+
+module.exports = require('soop')(SecureRandom);
diff --git a/test/index.html b/test/index.html
index 551c46d..9b8da7c 100644
--- a/test/index.html
+++ b/test/index.html
@@ -35,6 +35,7 @@
+
diff --git a/test/test.SecureRandom.js b/test/test.SecureRandom.js
new file mode 100644
index 0000000..ab8207b
--- /dev/null
+++ b/test/test.SecureRandom.js
@@ -0,0 +1,57 @@
+'use strict';
+
+var chai = chai || require('chai');
+var bitcore = bitcore || require('../bitcore');
+var should = chai.should();
+var assert = chai.assert;
+var SecureRandom = bitcore.SecureRandom;
+
+describe('SecureRandom', function() {
+
+ describe('getRandomBuffer', function() {
+
+ it('should return a buffer', function() {
+ var bytes = SecureRandom.getRandomBuffer(8);
+ bytes.length.should.equal(8);
+ Buffer.isBuffer(bytes).should.equal(true);
+ });
+
+ it('should not equate two 256 bit random buffers', function() {
+ var bytes1 = SecureRandom.getRandomBuffer(32);
+ var bytes2 = SecureRandom.getRandomBuffer(32);
+ bytes1.toString('hex').should.not.equal(bytes2.toString('hex'));
+ });
+
+ });
+
+ describe('getPseudoRandomBuffer', function() {
+
+ it('should generate 7 random bytes', function() {
+ var buf = SecureRandom.getPseudoRandomBuffer(7);
+ buf.length.should.equal(7);
+ });
+
+ it('should generate 8 random bytes', function() {
+ var buf = SecureRandom.getPseudoRandomBuffer(8);
+ buf.length.should.equal(8);
+ });
+
+ it('should generate 9 random bytes', function() {
+ var buf = SecureRandom.getPseudoRandomBuffer(9);
+ buf.length.should.equal(9);
+ });
+
+ it('should generate 90 random bytes', function() {
+ var buf = SecureRandom.getPseudoRandomBuffer(90);
+ buf.length.should.equal(90);
+ });
+
+ it('should generate two 8 byte buffers that are not equal', function() {
+ var buf1 = SecureRandom.getPseudoRandomBuffer(8);
+ var buf2 = SecureRandom.getPseudoRandomBuffer(8);
+ buf1.toString('hex').should.not.equal(buf2.toString('hex'));
+ });
+
+ });
+
+});
diff --git a/util/util.js b/util/util.js
index f89dce8..a59df4b 100644
--- a/util/util.js
+++ b/util/util.js
@@ -10,7 +10,6 @@ if (inBrowser) {
browser = require('../browser/vendor-bundle.js');
}
-
var sha256 = exports.sha256 = function(data) {
return new Buffer(crypto.createHash('sha256').update(data).digest('binary'), 'binary');
};
@@ -336,36 +335,6 @@ var createSynchrotron = exports.createSynchrotron = function(fn) {
};
};
-/**
- * Generate a random 64-bit number.
- *
- * With ideas from node-uuid:
- * Copyright (c) 2010 Robert Kieffer
- * https://github.com/broofa/node-uuid/
- *
- * @returns Buffer random nonce
- */
-var generateNonce = exports.generateNonce = function() {
- var b32 = 0x100000000,
- ff = 0xff;
- var b = new Buffer(8),
- i = 0;
-
- // Generate eight random bytes
- r = Math.random() * b32;
- b[i++] = r & ff;
- b[i++] = (r = r >>> 8) & ff;
- b[i++] = (r = r >>> 8) & ff;
- b[i++] = (r = r >>> 8) & ff;
- r = Math.random() * b32;
- b[i++] = r & ff;
- b[i++] = (r = r >>> 8) & ff;
- b[i++] = (r = r >>> 8) & ff;
- b[i++] = (r = r >>> 8) & ff;
-
- return b;
-};
-
/**
* Decode difficulty bits.
*