update key signing to use new SecureRandom

...and throw an error if you try to use the old, non-secure random number
generator.
This commit is contained in:
Ryan X. Charles 2014-04-25 15:00:51 -03:00
parent 66b8b6d0ba
commit c7b33eca9a
4 changed files with 64 additions and 7 deletions

View File

@ -7,7 +7,7 @@ Bitcoin.ECKey = (function () {
if (!input) {
// Generate new key
var n = ecparams.getN();
this.priv = ECDSA.getBigRandom(n);
//this.priv = ECDSA.getBigRandom(n);
} else if (input instanceof BigInteger) {
// Input is a private key value
this.priv = input;

View File

@ -65,4 +65,6 @@ function rng_get_bytes(ba) {
function SecureRandom() {}
SecureRandom.prototype.nextBytes = rng_get_bytes;
SecureRandom.prototype.nextBytes = function() {
throw new Error('Should not use old RNG');
};

View File

@ -90,6 +90,62 @@ Key.prototype.regenerateSync = function() {
};
Key.prototype.signSync = function(hash) {
var getSECCurveByName = require('../../browser/vendor-bundle.js').getSECCurveByName;
var BigInteger = require('../../browser/vendor-bundle.js').BigInteger;
var rng = new SecureRandom();
var ecparams = getSECCurveByName('secp256k1');
var rng = {};
rng.nextBytes = function(array) {
var buf = SecureRandom.getRandomBuffer(array.length);
var a = bufferToArray(SecureRandom.getRandomBuffer(array.length));
for (var i in array) {
array[i] = a[i];
}
};
var getBigRandom = function (limit) {
return new BigInteger(limit.bitLength(), rng)
.mod(limit.subtract(BigInteger.ONE))
.add(BigInteger.ONE);
};
var sign = function (hash, priv) {
var d = priv;
var n = ecparams.getN();
var e = BigInteger.fromByteArrayUnsigned(hash);
do {
var k = getBigRandom(n);
var G = ecparams.getG();
var Q = G.multiply(k);
var r = Q.getX().toBigInteger().mod(n);
} while (r.compareTo(BigInteger.ZERO) <= 0);
var s = k.modInverse(n).multiply(e.add(d.multiply(r))).mod(n);
return serializeSig(r, s);
};
var serializeSig = function (r, s) {
var rBa = r.toByteArraySigned();
var sBa = s.toByteArraySigned();
var sequence = [];
sequence.push(0x02); // INTEGER
sequence.push(rBa.length);
sequence = sequence.concat(rBa);
sequence.push(0x02); // INTEGER
sequence.push(sBa.length);
sequence = sequence.concat(sBa);
sequence.unshift(sequence.length);
sequence.unshift(0x30); // SEQUENCE
return sequence;
};
if (!this.private) {
throw new Error('Key does not have a private key set');
}
@ -97,10 +153,10 @@ Key.prototype.signSync = function(hash) {
if (!Buffer.isBuffer(hash) || hash.length !== 32) {
throw new Error('Arg should be a 32 bytes hash buffer');
}
var eck = new ECKey(this.private.toString('hex'));
eck.setCompressed(this._compressed);
var signature = eck.sign(bufferToArray(hash));
// return it as a buffer to keep c++ compatibility
var privhex = this.private.toString('hex');
var privnum = new BigInteger(privhex, 16);
var signature = sign(bufferToArray(hash), privnum);
return new Buffer(signature);
};

View File

@ -4,7 +4,6 @@ var imports = require('soop').imports();
var Key = imports.Key || require('./Key');
var bignum = imports.bignum || require('bignum');
var assert = require('assert');
var ECKey = require('../../browser/vendor-bundle.js').ECKey;
var ECPointFp = require('../../browser/vendor-bundle.js').ECPointFp;
var ECFieldElementFp = require('../../browser/vendor-bundle.js').ECFieldElementFp;
var getSECCurveByName = require('../../browser/vendor-bundle.js').getSECCurveByName;