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) { if (buffer.length !== 65) throw new Error('Invalid signature length') 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 r = BigInteger.fromBuffer(buffer.slice(1, 33)) var s = BigInteger.fromBuffer(buffer.slice(33)) return { compressed: compressed, i: recoveryParam, signature: 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 = 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 r = new Buffer(this.r.toDERInteger()) var s = new Buffer(this.s.toDERInteger()) return bip66.encode(r, s) } ECSignature.prototype.toScriptSignature = function (hashType) { var hashTypeMod = hashType & ~0x80 if (hashTypeMod <= 0 || hashTypeMod >= 4) throw new Error('Invalid hashType ' + hashType) var hashTypeBuffer = new Buffer(1) hashTypeBuffer.writeUInt8(hashType, 0) return Buffer.concat([this.toDER(), hashTypeBuffer]) } module.exports = ECSignature