|
|
@ -32,39 +32,63 @@ ECSignature.parseCompact = function (buffer) { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// Strict DER - https://github.com/bitcoin/bips/blob/master/bip-0066.mediawiki
|
|
|
|
// NOTE: SIGHASH byte ignored
|
|
|
|
ECSignature.fromDER = function (buffer) { |
|
|
|
assert.equal(buffer.readUInt8(0), 0x30, 'Not a DER sequence') |
|
|
|
assert.equal(buffer.readUInt8(1), buffer.length - 2, 'Invalid sequence length') |
|
|
|
assert.equal(buffer.readUInt8(2), 0x02, 'Expected a DER integer') |
|
|
|
// Minimum and maximum size constraints.
|
|
|
|
if (buffer.length < 9) throw new Error('Invalid sequence length') |
|
|
|
if (buffer.length > 73) throw new Error('Invalid sequence length') |
|
|
|
|
|
|
|
var rLen = buffer.readUInt8(3) |
|
|
|
assert(rLen > 0, 'R length is zero') |
|
|
|
// A signature is of type 0x30 (compound).
|
|
|
|
if (buffer[0] !== 0x30) throw new Error('Not a DER sequence') |
|
|
|
|
|
|
|
var offset = 4 + rLen |
|
|
|
assert.equal(buffer.readUInt8(offset), 0x02, 'Expected a DER integer (2)') |
|
|
|
// Make sure the length covers the entire signature.
|
|
|
|
if (buffer[1] !== buffer.length - 2) throw new Error('Invalid sequence length') |
|
|
|
|
|
|
|
var sLen = buffer.readUInt8(offset + 1) |
|
|
|
assert(sLen > 0, 'S length is zero') |
|
|
|
// Check whether the R element is an integer.
|
|
|
|
if (buffer[2] !== 0x02) throw new Error('Expected a DER integer') |
|
|
|
|
|
|
|
var rB = buffer.slice(4, offset) |
|
|
|
var sB = buffer.slice(offset + 2) |
|
|
|
offset += 2 + sLen |
|
|
|
// Extract the length of the R element.
|
|
|
|
var lenR = buffer.readUInt8(3) |
|
|
|
|
|
|
|
if (rLen > 1 && rB.readUInt8(0) === 0x00) { |
|
|
|
assert(rB.readUInt8(1) & 0x80, 'R value excessively padded') |
|
|
|
} |
|
|
|
// Zero-length integers are not allowed for R.
|
|
|
|
if (lenR === 0) throw new Error('R length is zero') |
|
|
|
|
|
|
|
if (sLen > 1 && sB.readUInt8(0) === 0x00) { |
|
|
|
assert(sB.readUInt8(1) & 0x80, 'S value excessively padded') |
|
|
|
} |
|
|
|
// Make sure the length of the R element is still inside the signature.
|
|
|
|
if (5 + lenR >= buffer.length) throw new Error('Invalid DER encoding') |
|
|
|
|
|
|
|
// Check whether the S element is an integer.
|
|
|
|
if (buffer[4 + lenR] !== 0x02) throw new Error('Expected a DER integer (2)') |
|
|
|
|
|
|
|
var lenS = buffer[5 + lenR] |
|
|
|
|
|
|
|
// Zero-length integers are not allowed for S.
|
|
|
|
if (lenS === 0) throw new Error('S length is zero') |
|
|
|
|
|
|
|
// Verify that the length of the signature matches the sum of the length
|
|
|
|
// of the elements.
|
|
|
|
if ((lenR + lenS + 6) !== buffer.length) throw new Error('Invalid DER encoding (2)') |
|
|
|
|
|
|
|
assert.equal(offset, buffer.length, 'Invalid DER encoding') |
|
|
|
// Negative numbers are not allowed for R.
|
|
|
|
if (buffer[4] & 0x80) throw new Error('R value is negative') |
|
|
|
|
|
|
|
// Null bytes at the start of R are not allowed, unless R would
|
|
|
|
// otherwise be interpreted as a negative number.
|
|
|
|
if (lenR > 1 && (buffer[4] === 0x00) && !(buffer[5] & 0x80)) throw new Error('R value excessively padded') |
|
|
|
|
|
|
|
// Negative numbers are not allowed for S.
|
|
|
|
if (buffer[lenR + 6] & 0x80) throw new Error('S value is negative') |
|
|
|
|
|
|
|
// Null bytes at the start of S are not allowed, unless S would otherwise be
|
|
|
|
// interpreted as a negative number.
|
|
|
|
if (lenS > 1 && (buffer[lenR + 6] === 0x00) && !(buffer[lenR + 7] & 0x80)) throw new Error('S value excessively padded') |
|
|
|
|
|
|
|
// non-BIP66 - extract R, S values
|
|
|
|
var rB = buffer.slice(4, 4 + lenR) |
|
|
|
var sB = buffer.slice(lenR + 6) |
|
|
|
var r = BigInteger.fromDERInteger(rB) |
|
|
|
var s = BigInteger.fromDERInteger(sB) |
|
|
|
|
|
|
|
assert(r.signum() >= 0, 'R value is negative') |
|
|
|
assert(s.signum() >= 0, 'S value is negative') |
|
|
|
|
|
|
|
return new ECSignature(r, s) |
|
|
|
} |
|
|
|
|
|
|
|