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.
This commit is contained in:
parent
a4de03af4d
commit
27ec74ba8a
4 changed files with 49 additions and 19 deletions
11
base58.js
11
base58.js
|
@ -12,7 +12,11 @@
|
||||||
* Ported to JavaScript by Stefan Thomas.
|
* Ported to JavaScript by Stefan Thomas.
|
||||||
*/
|
*/
|
||||||
encode: function (input) {
|
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 = [];
|
var chars = [];
|
||||||
|
|
||||||
while (bi.compareTo(B58.base) >= 0) {
|
while (bi.compareTo(B58.base) >= 0) {
|
||||||
|
@ -55,10 +59,7 @@
|
||||||
}
|
}
|
||||||
var bytes = bi.toByteArrayUnsigned();
|
var bytes = bi.toByteArrayUnsigned();
|
||||||
|
|
||||||
// Remove leading zeros arbitrarily added by BigInteger
|
// Add leading zeros
|
||||||
while (bytes[0] == 0) bytes.shift();
|
|
||||||
|
|
||||||
// Add right amount of leading zeros
|
|
||||||
while (leadingZerosNum-- > 0) bytes.unshift(0);
|
while (leadingZerosNum-- > 0) bytes.unshift(0);
|
||||||
|
|
||||||
return bytes;
|
return bytes;
|
||||||
|
|
22
ecdsa.js
22
ecdsa.js
|
@ -41,12 +41,20 @@ ECPointFp.prototype.getEncoded = function (compressed) {
|
||||||
|
|
||||||
ECPointFp.decodeFrom = function (curve, enc) {
|
ECPointFp.decodeFrom = function (curve, enc) {
|
||||||
var type = enc.shift();
|
var type = enc.shift();
|
||||||
|
|
||||||
|
// Extract x and y as byte arrays
|
||||||
var xBa = enc.slice(0, enc.length/2);
|
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);
|
var yBa = enc.slice(enc.length/2, enc.length);
|
||||||
|
|
||||||
|
// Prepend zero byte to prevent interpretation as negative integer
|
||||||
|
xBa.unshift(0);
|
||||||
yBa.unshift(0);
|
yBa.unshift(0);
|
||||||
|
|
||||||
|
// Convert to BigIntegers
|
||||||
|
var x = new BigInteger(xBa);
|
||||||
var y = new BigInteger(yBa);
|
var y = new BigInteger(yBa);
|
||||||
|
|
||||||
|
// Return point
|
||||||
return new ECPointFp(curve, curve.fromBigInteger(x), curve.fromBigInteger(y));
|
return new ECPointFp(curve, curve.fromBigInteger(x), curve.fromBigInteger(y));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -185,8 +193,7 @@ Bitcoin.ECDSA = (function () {
|
||||||
sign: function (hash, priv) {
|
sign: function (hash, priv) {
|
||||||
var d = priv;
|
var d = priv;
|
||||||
var n = ecparams.getN();
|
var n = ecparams.getN();
|
||||||
hash.unshift(0)
|
var e = BigInteger.fromByteArrayUnsigned(hash);
|
||||||
var e = new BigInteger(hash);
|
|
||||||
|
|
||||||
console.log("signhash: "+ Crypto.util.bytesToHex(hash));
|
console.log("signhash: "+ Crypto.util.bytesToHex(hash));
|
||||||
console.log("e: "+ Crypto.util.bytesToHex(e.toByteArrayUnsigned()));
|
console.log("e: "+ Crypto.util.bytesToHex(e.toByteArrayUnsigned()));
|
||||||
|
@ -246,13 +253,12 @@ Bitcoin.ECDSA = (function () {
|
||||||
// throw new Error("Extra bytes in signature");
|
// throw new Error("Extra bytes in signature");
|
||||||
|
|
||||||
var n = ecparams.getN();
|
var n = ecparams.getN();
|
||||||
hash.unshift(0)
|
var e = BigInteger.fromByteArrayUnsigned(hash);
|
||||||
var e = new BigInteger(hash);
|
|
||||||
|
|
||||||
console.log("e: "+ Crypto.util.bytesToHex(e.toByteArrayUnsigned()));
|
console.log("e: "+ Crypto.util.bytesToHex(e.toByteArrayUnsigned()));
|
||||||
|
|
||||||
var r = new BigInteger(rBa);
|
var r = BigInteger.fromByteArrayUnsigned(rBa);
|
||||||
var s = new BigInteger(sBa);
|
var s = BigInteger.fromByteArrayUnsigned(sBa);
|
||||||
|
|
||||||
if (r.compareTo(BigInteger.ONE) < 0 ||
|
if (r.compareTo(BigInteger.ONE) < 0 ||
|
||||||
r.compareTo(n) >= 0)
|
r.compareTo(n) >= 0)
|
||||||
|
|
6
eckey.js
6
eckey.js
|
@ -12,9 +12,11 @@ Bitcoin.ECKey = (function () {
|
||||||
// Input is a private key value
|
// Input is a private key value
|
||||||
this.priv = input;
|
this.priv = input;
|
||||||
} else if (Bitcoin.Util.isArray(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) {
|
} 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));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
23
util.js
23
util.js
|
@ -2,9 +2,28 @@
|
||||||
BigInteger.valueOf = nbv;
|
BigInteger.valueOf = nbv;
|
||||||
BigInteger.prototype.toByteArrayUnsigned = function () {
|
BigInteger.prototype.toByteArrayUnsigned = function () {
|
||||||
var ba = this.toByteArray();
|
var ba = this.toByteArray();
|
||||||
|
if (ba.length) {
|
||||||
|
if (ba[0] == 0) {
|
||||||
|
ba = ba.slice(1);
|
||||||
|
}
|
||||||
return ba.map(function (v) {
|
return ba.map(function (v) {
|
||||||
return (v < 0) ? v + 256 : 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
|
// Console ignore
|
||||||
|
@ -48,7 +67,9 @@ Bitcoin.Util = {
|
||||||
},
|
},
|
||||||
valueToBigInt: function (valueBuffer) {
|
valueToBigInt: function (valueBuffer) {
|
||||||
if (valueBuffer instanceof BigInteger) return 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) {
|
formatValue: function (valueBuffer) {
|
||||||
var value = this.valueToBigInt(valueBuffer).toString();
|
var value = this.valueToBigInt(valueBuffer).toString();
|
||||||
|
|
Loading…
Reference in a new issue