diff --git a/lib/crypto/signature.js b/lib/crypto/signature.js index 142bd06..8b6fbd2 100644 --- a/lib/crypto/signature.js +++ b/lib/crypto/signature.js @@ -24,48 +24,55 @@ Signature.prototype.set = function(obj) { return this; }; -Signature.prototype.fromCompact = function(buf) { +Signature.fromCompact = function(buf) { + var sig = new Signature(); var compressed = true; var i = buf.slice(0, 1)[0] - 27 - 4; //TODO: handle uncompressed pubkeys - /* - if (i < 0) { - compressed = false; - i = i + 4; - } - */ var b2 = buf.slice(1, 33); var b3 = buf.slice(33, 65); - if (!(i === 0 || i === 1 || i === 2 || i === 3)) + if (!(i === 0 || i === 1 || i === 2 || i === 3)) { throw new Error('i must be 0, 1, 2, or 3'); - if (b2.length !== 32) + } + if (b2.length !== 32) { throw new Error('r must be 32 bytes'); - if (b3.length !== 32) + } + if (b3.length !== 32) { throw new Error('s must be 32 bytes'); + } - this.compressed = compressed; - this.i = i; - this.r = BN().fromBuffer(b2); - this.s = BN().fromBuffer(b3); + sig.compressed = compressed; + sig.i = i; + sig.r = BN().fromBuffer(b2); + sig.s = BN().fromBuffer(b3); - return this; + return sig; }; -Signature.prototype.fromDER = function(buf) { +Signature.fromDER = function(buf) { var obj = Signature.parseDER(buf); - this.r = obj.r; - this.s = obj.s; + var sig = new Signature(); - return this; + sig.r = obj.r; + sig.s = obj.s; + + return sig; }; -Signature.prototype.fromString = function(str) { - var buf = new Buffer(str, 'hex'); - this.fromDER(buf); +// The format used in a tx +Signature.fromTxFormat = function(buf) { + var nhashtype = buf.readUInt8(buf.length - 1); + var derbuf = buf.slice(0, buf.length - 1); + var sig = new Signature.fromDER(derbuf, false); + sig.nhashtype = nhashtype; + return sig; +}; - return this; +Signature.fromString = function(str) { + var buf = new Buffer(str, 'hex'); + return Signature.fromDER(buf); }; Signature.parseDER = function(buf) { diff --git a/test/crypto/signature.js b/test/crypto/signature.js index 43b3f31..8036457 100644 --- a/test/crypto/signature.js +++ b/test/crypto/signature.js @@ -41,8 +41,7 @@ describe('Signature', function() { blank, blank ]); - var sig = new Signature(); - sig.fromCompact(compressed); + var sig = new Signature.fromCompact(compressed); sig.r.cmp(0).should.equal(0); sig.s.cmp(0).should.equal(0); }); @@ -54,8 +53,7 @@ describe('Signature', function() { var buf = new Buffer('3044022075fc517e541bd54769c080b64397e32161c850f6c1b2b67a5c433affbb3e62770220729e85cc46ffab881065ec07694220e71d4df9b2b8c8fd12c3122cf3a5efbcf2', 'hex'); it('should parse this DER format signature', function() { - var sig = new Signature(); - sig.fromDER(buf); + var sig = new Signature.fromDER(buf); sig.r.toBuffer({ size: 32 }).toString('hex').should.equal('75fc517e541bd54769c080b64397e32161c850f6c1b2b67a5c433affbb3e6277'); @@ -71,8 +69,7 @@ describe('Signature', function() { var buf = new Buffer('3044022075fc517e541bd54769c080b64397e32161c850f6c1b2b67a5c433affbb3e62770220729e85cc46ffab881065ec07694220e71d4df9b2b8c8fd12c3122cf3a5efbcf2', 'hex'); it('should parse this DER format signature in hex', function() { - var sig = new Signature(); - sig.fromString(buf.toString('hex')); + var sig = new Signature.fromString(buf.toString('hex')); sig.r.toBuffer({ size: 32 }).toString('hex').should.equal('75fc517e541bd54769c080b64397e32161c850f6c1b2b67a5c433affbb3e6277'); @@ -83,6 +80,25 @@ describe('Signature', function() { }); + describe('#fromTxFormat', function() { + + it('should convert from this known tx-format buffer', function() { + var buf = new Buffer('30450221008bab1f0a2ff2f9cb8992173d8ad73c229d31ea8e10b0f4d4ae1a0d8ed76021fa02200993a6ec81755b9111762fc2cf8e3ede73047515622792110867d12654275e7201', 'hex'); + var sig = Signature.fromTxFormat(buf); + sig.r.toString().should.equal('63173831029936981022572627018246571655303050627048489594159321588908385378810'); + sig.s.toString().should.equal('4331694221846364448463828256391194279133231453999942381442030409253074198130'); + sig.nhashtype.should.equal(Signature.SIGHASH_ALL); + }); + + it('should parse this known signature and rebuild it', function() { + var hex = "3044022007415aa37ce7eaa6146001ac8bdefca0ddcba0e37c5dc08c4ac99392124ebac802207d382307fd53f65778b07b9c63b6e196edeadf0be719130c5db21ff1e700d67501"; + var buf = new Buffer(hex, 'hex'); + var sig = Signature.fromTxFormat(buf); + sig.toTxFormat().toString('hex').should.equal(hex); + }); + + }); + describe('#parseDER', function() { it('should parse this signature generated in node', function() {