Merge pull request #36 from bitcoinjs/replace-rng
Replace all Math.random/other (P)RNG
This commit is contained in:
commit
771d415179
8 changed files with 18 additions and 141 deletions
|
@ -40,6 +40,7 @@
|
||||||
"compile": "./node_modules/.bin/browserify ./src/index.js -s Bitcoin | ./node_modules/.bin/uglifyjs > bitcoinjs-min.js"
|
"compile": "./node_modules/.bin/browserify ./src/index.js -s Bitcoin | ./node_modules/.bin/uglifyjs > bitcoinjs-min.js"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"crypto-js": "3.1.2-2"
|
"crypto-js": "3.1.2-2",
|
||||||
|
"secure-random": "0.2.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
var sec = require('./jsbn/sec');
|
var sec = require('./jsbn/sec');
|
||||||
var SecureRandom = require('./jsbn/rng');
|
var rng = require('secure-random');
|
||||||
var BigInteger = require('./jsbn/jsbn');
|
var BigInteger = require('./jsbn/jsbn');
|
||||||
var convert = require('./convert')
|
var convert = require('./convert')
|
||||||
var HmacSHA256 = require('crypto-js/hmac-sha256');
|
var HmacSHA256 = require('crypto-js/hmac-sha256');
|
||||||
|
|
||||||
var ECPointFp = require('./jsbn/ec').ECPointFp;
|
var ECPointFp = require('./jsbn/ec').ECPointFp;
|
||||||
|
|
||||||
var rng = new SecureRandom();
|
|
||||||
var ecparams = sec("secp256k1");
|
var ecparams = sec("secp256k1");
|
||||||
var P_OVER_FOUR = null;
|
var P_OVER_FOUR = null;
|
||||||
|
|
||||||
|
|
|
@ -672,9 +672,9 @@ function bnpFromNumber(a,b,c) {
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// new BigInteger(int,RNG)
|
// new BigInteger(int,RNG)
|
||||||
var x = new Array(), t = a&7;
|
var t = a&7;
|
||||||
x.length = (a>>3)+1;
|
var length = (a>>3)+1;
|
||||||
b.nextBytes(x);
|
var x = b(length, {array: true});
|
||||||
if(t > 0) x[0] &= ((1<<t)-1); else x[0] = 0;
|
if(t > 0) x[0] &= ((1<<t)-1); else x[0] = 0;
|
||||||
self.fromString(x,256);
|
self.fromString(x,256);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,39 +0,0 @@
|
||||||
// prng4.js - uses Arcfour as a PRNG
|
|
||||||
|
|
||||||
function Arcfour() {
|
|
||||||
this.i = 0;
|
|
||||||
this.j = 0;
|
|
||||||
this.S = new Array();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize arcfour context from key, an array of ints, each from [0..255]
|
|
||||||
function ARC4init(key) {
|
|
||||||
var i, j, t;
|
|
||||||
for(i = 0; i < 256; ++i)
|
|
||||||
this.S[i] = i;
|
|
||||||
j = 0;
|
|
||||||
for(i = 0; i < 256; ++i) {
|
|
||||||
j = (j + this.S[i] + key[i % key.length]) & 255;
|
|
||||||
t = this.S[i];
|
|
||||||
this.S[i] = this.S[j];
|
|
||||||
this.S[j] = t;
|
|
||||||
}
|
|
||||||
this.i = 0;
|
|
||||||
this.j = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
function ARC4next() {
|
|
||||||
var t;
|
|
||||||
this.i = (this.i + 1) & 255;
|
|
||||||
this.j = (this.j + this.S[this.i]) & 255;
|
|
||||||
t = this.S[this.i];
|
|
||||||
this.S[this.i] = this.S[this.j];
|
|
||||||
this.S[this.j] = t;
|
|
||||||
return this.S[(t + this.S[this.i]) & 255];
|
|
||||||
}
|
|
||||||
|
|
||||||
Arcfour.prototype.init = ARC4init;
|
|
||||||
Arcfour.prototype.next = ARC4next;
|
|
||||||
|
|
||||||
module.exports = Arcfour;
|
|
||||||
|
|
|
@ -1,85 +0,0 @@
|
||||||
// Random number generator - requires a PRNG backend, e.g. prng4.js
|
|
||||||
// prng4.js - uses Arcfour as a PRNG
|
|
||||||
|
|
||||||
var Arcfour = require('./prng4');
|
|
||||||
|
|
||||||
// Plug in your RNG constructor here
|
|
||||||
function prng_newstate() {
|
|
||||||
return new Arcfour();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pool size must be a multiple of 4 and greater than 32.
|
|
||||||
// An array of bytes the size of the pool will be passed to init()
|
|
||||||
var rng_psize = 256;
|
|
||||||
|
|
||||||
// For best results, put code like
|
|
||||||
// <body onClick='rng_seed_time();' onKeyPress='rng_seed_time();'>
|
|
||||||
// in your main HTML document.
|
|
||||||
|
|
||||||
var rng_state;
|
|
||||||
var rng_pool;
|
|
||||||
var rng_pptr;
|
|
||||||
|
|
||||||
// Mix in a 32-bit integer into the pool
|
|
||||||
function rng_seed_int(x) {
|
|
||||||
rng_pool[rng_pptr++] ^= x & 255;
|
|
||||||
rng_pool[rng_pptr++] ^= (x >> 8) & 255;
|
|
||||||
rng_pool[rng_pptr++] ^= (x >> 16) & 255;
|
|
||||||
rng_pool[rng_pptr++] ^= (x >> 24) & 255;
|
|
||||||
if(rng_pptr >= rng_psize) rng_pptr -= rng_psize;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mix in the current time (w/milliseconds) into the pool
|
|
||||||
function rng_seed_time() {
|
|
||||||
rng_seed_int(new Date().getTime());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize the pool with junk if needed.
|
|
||||||
if(rng_pool == null) {
|
|
||||||
rng_pool = new Array();
|
|
||||||
rng_pptr = 0;
|
|
||||||
var t;
|
|
||||||
// TODO(shtylman) use browser crypto if available
|
|
||||||
/*
|
|
||||||
if(navigator.appName == "Netscape" && navigator.appVersion < "5" && window.crypto) {
|
|
||||||
// Extract entropy (256 bits) from NS4 RNG if available
|
|
||||||
var z = window.crypto.random(32);
|
|
||||||
for(t = 0; t < z.length; ++t)
|
|
||||||
rng_pool[rng_pptr++] = z.charCodeAt(t) & 255;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
while(rng_pptr < rng_psize) { // extract some randomness from Math.random()
|
|
||||||
t = Math.floor(65536 * Math.random());
|
|
||||||
rng_pool[rng_pptr++] = t >>> 8;
|
|
||||||
rng_pool[rng_pptr++] = t & 255;
|
|
||||||
}
|
|
||||||
rng_pptr = 0;
|
|
||||||
rng_seed_time();
|
|
||||||
//rng_seed_int(window.screenX);
|
|
||||||
//rng_seed_int(window.screenY);
|
|
||||||
}
|
|
||||||
|
|
||||||
function rng_get_byte() {
|
|
||||||
if(rng_state == null) {
|
|
||||||
rng_seed_time();
|
|
||||||
rng_state = prng_newstate();
|
|
||||||
rng_state.init(rng_pool);
|
|
||||||
for(rng_pptr = 0; rng_pptr < rng_pool.length; ++rng_pptr)
|
|
||||||
rng_pool[rng_pptr] = 0;
|
|
||||||
rng_pptr = 0;
|
|
||||||
//rng_pool = null;
|
|
||||||
}
|
|
||||||
// TODO: allow reseeding after first request
|
|
||||||
return rng_state.next();
|
|
||||||
}
|
|
||||||
|
|
||||||
function rng_get_bytes(ba) {
|
|
||||||
var i;
|
|
||||||
for(i = 0; i < ba.length; ++i) ba[i] = rng_get_byte();
|
|
||||||
}
|
|
||||||
|
|
||||||
function SecureRandom() {}
|
|
||||||
|
|
||||||
SecureRandom.prototype.nextBytes = rng_get_bytes;
|
|
||||||
|
|
||||||
module.exports = SecureRandom;
|
|
|
@ -7,8 +7,7 @@ var Transaction = require('./transaction').Transaction;
|
||||||
var TransactionIn = require('./transaction').TransactionIn;
|
var TransactionIn = require('./transaction').TransactionIn;
|
||||||
var TransactionOut = require('./transaction').TransactionOut;
|
var TransactionOut = require('./transaction').TransactionOut;
|
||||||
var HDNode = require('./hdwallet.js')
|
var HDNode = require('./hdwallet.js')
|
||||||
var SecureRandom = require('./jsbn/rng');
|
var rng = require('secure-random');
|
||||||
var rng = new SecureRandom();
|
|
||||||
|
|
||||||
var Wallet = function (seed, options) {
|
var Wallet = function (seed, options) {
|
||||||
if (!(this instanceof Wallet)) { return new Wallet(seed, options); }
|
if (!(this instanceof Wallet)) { return new Wallet(seed, options); }
|
||||||
|
@ -32,10 +31,7 @@ var Wallet = function (seed, options) {
|
||||||
|
|
||||||
// Make a new master key
|
// Make a new master key
|
||||||
this.newMasterKey = function(seed, network) {
|
this.newMasterKey = function(seed, network) {
|
||||||
if (!seed) {
|
if (!seed) seed= rng(32, { array: true })
|
||||||
var seed= new Array(32);
|
|
||||||
rng.nextBytes(seed);
|
|
||||||
}
|
|
||||||
masterkey = new HDNode(seed, network);
|
masterkey = new HDNode(seed, network);
|
||||||
|
|
||||||
// HD first-level child derivation method should be private
|
// HD first-level child derivation method should be private
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
var assert = require('assert');
|
var assert = require('assert');
|
||||||
var BigInteger = require('../src/jsbn/jsbn.js')
|
var BigInteger = require('../src/jsbn/jsbn.js')
|
||||||
var bytesToHex = require('../src/convert.js').bytesToHex;
|
var bytesToHex = require('../src/convert.js').bytesToHex;
|
||||||
|
var secureRandom = require('secure-random');
|
||||||
|
|
||||||
describe('BigInteger', function() {
|
describe('BigInteger', function() {
|
||||||
describe('toByteArraySigned', function() {
|
describe('toByteArraySigned', function() {
|
||||||
|
@ -25,4 +26,12 @@ describe('BigInteger', function() {
|
||||||
assert.equal(hex(-62300), '0x80f35c');
|
assert.equal(hex(-62300), '0x80f35c');
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('with RNG passed into constructor as the 2nd argument', function(){
|
||||||
|
it('returns a BigInteger with the limit of the specified length', function(){
|
||||||
|
var bitLength = 256
|
||||||
|
var i = new BigInteger(bitLength, secureRandom)
|
||||||
|
assert(i.bitLength() <= 256)
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,13 +1,9 @@
|
||||||
/* global it */
|
|
||||||
var assert = require('assert');
|
var assert = require('assert');
|
||||||
var bitcoinjs = require('../');
|
var bitcoinjs = require('../');
|
||||||
var sec = require('../src/jsbn/sec');
|
var sec = require('../src/jsbn/sec');
|
||||||
var BigInteger = require('../src/jsbn/jsbn.js');
|
var BigInteger = require('../src/jsbn/jsbn.js');
|
||||||
var SHA256 = require('crypto-js/sha256');
|
var SHA256 = require('crypto-js/sha256');
|
||||||
|
var rng = require('secure-random');
|
||||||
var SecureRandom = require('../src/jsbn/rng');
|
|
||||||
var rng = new SecureRandom();
|
|
||||||
|
|
||||||
var ecparams = sec('secp256k1');
|
var ecparams = sec('secp256k1');
|
||||||
var ECPointFp = bitcoinjs.ECPointFp;
|
var ECPointFp = bitcoinjs.ECPointFp;
|
||||||
var convert = require('../src/convert');
|
var convert = require('../src/convert');
|
||||||
|
|
Loading…
Add table
Reference in a new issue