Browse Source

Fixed all cases of unsafe BigInteger <-> byte[] conversion.

The BigInteger class we're using supports negative integers and
encodes them with a sign bit. Since in our application we are dealing
with unsigned integers only, we need to disable this functionality by
creating two wrapper functions toByteArrayUnsigned and
fromByteArrayUnsigned.
hk-custom-address
Stefan Thomas 14 years ago
parent
commit
27ec74ba8a
  1. 11
      base58.js
  2. 22
      ecdsa.js
  3. 6
      eckey.js
  4. 29
      util.js

11
base58.js

@ -12,7 +12,11 @@
* Ported to JavaScript by Stefan Thomas.
*/
encode: function (input) {
var bi = new BigInteger(input);
console.log(input);
// We prepend the input with a zero byte because the BigInteger
// implementation treats it as a negative number if any of the
// four most significant bits are set.
var bi = BigInteger.fromByteArrayUnsigned(input);
var chars = [];
while (bi.compareTo(B58.base) >= 0) {
@ -55,10 +59,7 @@
}
var bytes = bi.toByteArrayUnsigned();
// Remove leading zeros arbitrarily added by BigInteger
while (bytes[0] == 0) bytes.shift();
// Add right amount of leading zeros
// Add leading zeros
while (leadingZerosNum-- > 0) bytes.unshift(0);
return bytes;

22
ecdsa.js

@ -41,12 +41,20 @@ ECPointFp.prototype.getEncoded = function (compressed) {
ECPointFp.decodeFrom = function (curve, enc) {
var type = enc.shift();
// Extract x and y as byte arrays
var xBa = enc.slice(0, enc.length/2);
xBa.unshift(0);
var x = new BigInteger(xBa);
var yBa = enc.slice(enc.length/2, enc.length);
// Prepend zero byte to prevent interpretation as negative integer
xBa.unshift(0);
yBa.unshift(0);
// Convert to BigIntegers
var x = new BigInteger(xBa);
var y = new BigInteger(yBa);
// Return point
return new ECPointFp(curve, curve.fromBigInteger(x), curve.fromBigInteger(y));
};
@ -185,8 +193,7 @@ Bitcoin.ECDSA = (function () {
sign: function (hash, priv) {
var d = priv;
var n = ecparams.getN();
hash.unshift(0)
var e = new BigInteger(hash);
var e = BigInteger.fromByteArrayUnsigned(hash);
console.log("signhash: "+ Crypto.util.bytesToHex(hash));
console.log("e: "+ Crypto.util.bytesToHex(e.toByteArrayUnsigned()));
@ -246,13 +253,12 @@ Bitcoin.ECDSA = (function () {
// throw new Error("Extra bytes in signature");
var n = ecparams.getN();
hash.unshift(0)
var e = new BigInteger(hash);
var e = BigInteger.fromByteArrayUnsigned(hash);
console.log("e: "+ Crypto.util.bytesToHex(e.toByteArrayUnsigned()));
var r = new BigInteger(rBa);
var s = new BigInteger(sBa);
var r = BigInteger.fromByteArrayUnsigned(rBa);
var s = BigInteger.fromByteArrayUnsigned(sBa);
if (r.compareTo(BigInteger.ONE) < 0 ||
r.compareTo(n) >= 0)

6
eckey.js

@ -12,9 +12,11 @@ Bitcoin.ECKey = (function () {
// Input is a private key value
this.priv = input;
} else if (Bitcoin.Util.isArray(input)) {
this.priv = new BigInteger(input);
// Prepend zero byte to prevent interpretation as negative integer
this.priv = BigInteger.fromByteArrayUnsigned(input);
} else if ("string" == typeof input) {
this.priv = new BigInteger(Crypto.util.base64ToBytes(input));
// Prepend zero byte to prevent interpretation as negative integer
this.priv = BigInteger.fromByteArrayUnsigned(Crypto.util.base64ToBytes(input));
}
};

29
util.js

@ -2,9 +2,28 @@
BigInteger.valueOf = nbv;
BigInteger.prototype.toByteArrayUnsigned = function () {
var ba = this.toByteArray();
return ba.map(function (v) {
return (v < 0) ? v + 256 : v;
});
if (ba.length) {
if (ba[0] == 0) {
ba = ba.slice(1);
}
return ba.map(function (v) {
return (v < 0) ? v + 256 : v;
});
} else {
// Empty array, nothing to do
return ba;
}
};
BigInteger.fromByteArrayUnsigned = function (ba) {
if (!ba.length) {
return ba.valueOf(0);
} else if (ba[0] & 0x80) {
// Prepend a zero so the BigInteger class doesn't mistake this
// for a negative integer.
return new BigInteger([0].concat(ba));
} else {
return new BigInteger(ba);
}
};
// Console ignore
@ -48,7 +67,9 @@ Bitcoin.Util = {
},
valueToBigInt: function (valueBuffer) {
if (valueBuffer instanceof BigInteger) return valueBuffer;
return new BigInteger(valueBuffer);
// Prepend zero byte to prevent interpretation as negative integer
return BigInteger.fromByteArrayUnsigned(valueBuffer);
},
formatValue: function (valueBuffer) {
var value = this.valueToBigInt(valueBuffer).toString();

Loading…
Cancel
Save