Fixed DER-encoding - expects signed integers.
Thanks to Ben Reeves for the report and Tomas Pomin for the solution. See http://crypto.stackexchange.com/questions/1795/converting-a-der-ecdsa-signature-to-asn-1
This commit is contained in:
parent
c2ce224d1b
commit
07f9d55ccb
2 changed files with 78 additions and 4 deletions
|
@ -305,8 +305,8 @@ Bitcoin.ECDSA = (function () {
|
||||||
* Takes two BigIntegers representing r and s and returns a byte array.
|
* Takes two BigIntegers representing r and s and returns a byte array.
|
||||||
*/
|
*/
|
||||||
serializeSig: function (r, s) {
|
serializeSig: function (r, s) {
|
||||||
var rBa = r.toByteArrayUnsigned();
|
var rBa = r.toByteArraySigned();
|
||||||
var sBa = s.toByteArrayUnsigned();
|
var sBa = s.toByteArraySigned();
|
||||||
|
|
||||||
var sequence = [];
|
var sequence = [];
|
||||||
sequence.push(0x02); // INTEGER
|
sequence.push(0x02); // INTEGER
|
||||||
|
@ -327,7 +327,7 @@ Bitcoin.ECDSA = (function () {
|
||||||
* Parses a byte array containing a DER-encoded signature.
|
* Parses a byte array containing a DER-encoded signature.
|
||||||
*
|
*
|
||||||
* This function will return an object of the form:
|
* This function will return an object of the form:
|
||||||
*
|
*
|
||||||
* {
|
* {
|
||||||
* r: BigInteger,
|
* r: BigInteger,
|
||||||
* s: BigInteger
|
* s: BigInteger
|
||||||
|
|
76
src/util.js
76
src/util.js
|
@ -1,7 +1,14 @@
|
||||||
// BigInteger monkey patching
|
// BigInteger monkey patching
|
||||||
BigInteger.valueOf = nbv;
|
BigInteger.valueOf = nbv;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a byte array representation of the big integer.
|
||||||
|
*
|
||||||
|
* This returns the absolute of the contained value in big endian
|
||||||
|
* form. A value of zero results in an empty array.
|
||||||
|
*/
|
||||||
BigInteger.prototype.toByteArrayUnsigned = function () {
|
BigInteger.prototype.toByteArrayUnsigned = function () {
|
||||||
var ba = this.toByteArray();
|
var ba = this.abs().toByteArray();
|
||||||
if (ba.length) {
|
if (ba.length) {
|
||||||
if (ba[0] == 0) {
|
if (ba[0] == 0) {
|
||||||
ba = ba.slice(1);
|
ba = ba.slice(1);
|
||||||
|
@ -14,6 +21,13 @@ BigInteger.prototype.toByteArrayUnsigned = function () {
|
||||||
return ba;
|
return ba;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Turns a byte array into a big integer.
|
||||||
|
*
|
||||||
|
* This function will interpret a byte array as a big integer in big
|
||||||
|
* endian notation and ignore leading zeros.
|
||||||
|
*/
|
||||||
BigInteger.fromByteArrayUnsigned = function (ba) {
|
BigInteger.fromByteArrayUnsigned = function (ba) {
|
||||||
if (!ba.length) {
|
if (!ba.length) {
|
||||||
return ba.valueOf(0);
|
return ba.valueOf(0);
|
||||||
|
@ -26,6 +40,66 @@ BigInteger.fromByteArrayUnsigned = function (ba) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts big integer to signed byte representation.
|
||||||
|
*
|
||||||
|
* The format for this value uses a the most significant bit as a sign
|
||||||
|
* bit. If the most significant bit is already occupied by the
|
||||||
|
* absolute value, an extra byte is prepended and the sign bit is set
|
||||||
|
* there.
|
||||||
|
*
|
||||||
|
* Examples:
|
||||||
|
*
|
||||||
|
* 0 => 0x00
|
||||||
|
* 1 => 0x01
|
||||||
|
* -1 => 0x81
|
||||||
|
* 127 => 0x7f
|
||||||
|
* -127 => 0xff
|
||||||
|
* 128 => 0x0080
|
||||||
|
* -128 => 0x8080
|
||||||
|
* 255 => 0x00ff
|
||||||
|
* -255 => 0x80ff
|
||||||
|
* 16300 => 0x3fac
|
||||||
|
* -16300 => 0xbfac
|
||||||
|
* 62300 => 0x00f35c
|
||||||
|
* -62300 => 0x80f35c
|
||||||
|
*/
|
||||||
|
BigInteger.prototype.toByteArraySigned = function () {
|
||||||
|
var val = this.abs().toByteArrayUnsigned();
|
||||||
|
var neg = this.compareTo(BigInteger.ZERO) < 0;
|
||||||
|
|
||||||
|
if (neg) {
|
||||||
|
if (val[0] & 0x80) {
|
||||||
|
val.unshift(0x80);
|
||||||
|
} else {
|
||||||
|
val[0] |= 0x80;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (val[0] & 0x80) {
|
||||||
|
val.unshift(0x00);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return val;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse a signed big integer byte representation.
|
||||||
|
*
|
||||||
|
* For details on the format please see BigInteger.toByteArraySigned.
|
||||||
|
*/
|
||||||
|
BigInteger.fromByteArraySigned = function (ba) {
|
||||||
|
// Check for negative value
|
||||||
|
if (ba[0] & 0x80) {
|
||||||
|
// Remove sign bit
|
||||||
|
ba[0] &= 0x7f;
|
||||||
|
|
||||||
|
return BigInteger.fromByteArrayUnsigned(ba).negate();
|
||||||
|
} else {
|
||||||
|
return BigInteger.fromByteArrayUnsigned(ba);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Console ignore
|
// Console ignore
|
||||||
var names = ["log", "debug", "info", "warn", "error", "assert", "dir",
|
var names = ["log", "debug", "info", "warn", "error", "assert", "dir",
|
||||||
"dirxml", "group", "groupEnd", "time", "timeEnd", "count",
|
"dirxml", "group", "groupEnd", "time", "timeEnd", "count",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue