You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

103 lines
2.5 KiB

var assert = require('assert')
var BigInteger = require('bigi')
function ECSignature(r, s) {
assert(r instanceof BigInteger, 'Expected BigInteger, got ' + r)
assert(s instanceof BigInteger, 'Expected BigInteger, got ' + s)
this.r = r
this.s = s
}
// Import operations
ECSignature.parseCompact = function(buffer) {
assert.equal(buffer.length, 65, 'Invalid signature length')
var i = buffer.readUInt8(0) - 27
// At most 3 bits
assert.equal(i, i & 7, 'Invalid signature parameter')
var compressed = !!(i & 4)
// Recovery param only
i = i & 3
var r = BigInteger.fromBuffer(buffer.slice(1, 33))
var s = BigInteger.fromBuffer(buffer.slice(33))
return {
compressed: compressed,
i: i,
signature: new ECSignature(r, s)
}
}
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')
var rLen = buffer.readUInt8(3)
var rB = buffer.slice(4, 4 + rLen)
var offset = 4 + rLen
assert.equal(buffer.readUInt8(offset), 0x02, 'Expected a DER integer (2)')
var sLen = buffer.readUInt8(1 + offset)
var sB = buffer.slice(2 + offset)
offset += 2 + sLen
assert.equal(offset, buffer.length, 'Invalid DER encoding')
var r = BigInteger.fromDERInteger(rB)
var s = BigInteger.fromDERInteger(sB)
return new ECSignature(r, s)
}
ECSignature.parseScriptSignature = function(buffer) {
return {
signature: ECSignature.fromDER(buffer.slice(0, -1)),
hashType: buffer.readUInt8(buffer.length - 1)
}
}
// Export operations
ECSignature.prototype.toCompact = function(i, compressed) {
if (compressed) i += 4
i += 27
var buffer = new Buffer(65)
buffer.writeUInt8(i, 0)
this.r.toBuffer(32).copy(buffer, 1)
this.s.toBuffer(32).copy(buffer, 33)
return buffer
}
ECSignature.prototype.toDER = function() {
var rBa = this.r.toDERInteger()
var sBa = this.s.toDERInteger()
var sequence = []
sequence.push(0x02) // INTEGER
sequence.push(rBa.length)
sequence = sequence.concat(rBa)
sequence.push(0x02) // INTEGER
sequence.push(sBa.length)
sequence = sequence.concat(sBa)
sequence.unshift(sequence.length)
sequence.unshift(0x30) // SEQUENCE
return new Buffer(sequence)
}
ECSignature.prototype.toScriptSignature = function(hashType) {
var hashTypeBuffer = new Buffer(1)
hashTypeBuffer.writeUInt8(hashType, 0)
return Buffer.concat([this.toDER(), hashTypeBuffer])
}
module.exports = ECSignature