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.
|
||||
*/
|
||||
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
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
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
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…
Add table
Reference in a new issue