var bip66 = require('bip66') var typeforce = require('typeforce') var types = require('./types') var BigInteger = require('bigi') function ECSignature (r, s) { typeforce(types.tuple(types.BigInt, types.BigInt), arguments) this.r = r this.s = s } ECSignature.parseCompact = function (buffer) { typeforce(types.BufferN(65), buffer) var flagByte = buffer.readUInt8(0) - 27 if (flagByte !== (flagByte & 7)) throw new Error('Invalid signature parameter') var compressed = !!(flagByte & 4) var recoveryParam = flagByte & 3 var signature = ECSignature.fromRSBuffer(buffer.slice(1)) return { compressed: compressed, i: recoveryParam, signature: signature } } ECSignature.fromRSBuffer = function (buffer) { typeforce(types.BufferN(64), buffer) var r = BigInteger.fromBuffer(buffer.slice(0, 32)) var s = BigInteger.fromBuffer(buffer.slice(32, 64)) return new ECSignature(r, s) } ECSignature.fromDER = function (buffer) { var decode = bip66.decode(buffer) var r = BigInteger.fromDERInteger(decode.r) var s = BigInteger.fromDERInteger(decode.s) return new ECSignature(r, s) } // BIP62: 1 byte hashType flag (only 0x01, 0x02, 0x03, 0x81, 0x82 and 0x83 are allowed) ECSignature.parseScriptSignature = function (buffer) { var hashType = buffer.readUInt8(buffer.length - 1) var hashTypeMod = hashType & ~0x80 if (hashTypeMod <= 0x00 || hashTypeMod >= 0x04) throw new Error('Invalid hashType ' + hashType) return { signature: ECSignature.fromDER(buffer.slice(0, -1)), hashType: hashType } } ECSignature.prototype.toCompact = function (i, compressed) { if (compressed) { i += 4 } i += 27 var buffer = Buffer.alloc(65) buffer.writeUInt8(i, 0) this.toRSBuffer(buffer, 1) return buffer } ECSignature.prototype.toDER = function () { var r = Buffer.from(this.r.toDERInteger()) var s = Buffer.from(this.s.toDERInteger()) return bip66.encode(r, s) } ECSignature.prototype.toRSBuffer = function (buffer, offset) { buffer = buffer || Buffer.alloc(64) this.r.toBuffer(32).copy(buffer, offset) this.s.toBuffer(32).copy(buffer, offset + 32) return buffer } ECSignature.prototype.toScriptSignature = function (hashType) { var hashTypeMod = hashType & ~0x80 if (hashTypeMod <= 0 || hashTypeMod >= 4) throw new Error('Invalid hashType ' + hashType) var hashTypeBuffer = Buffer.alloc(1) hashTypeBuffer.writeUInt8(hashType, 0) return Buffer.concat([this.toDER(), hashTypeBuffer]) } module.exports = ECSignature