sign/verify with uncompressed pubkeys

This commit is contained in:
Ryan X. Charles 2014-08-22 19:43:32 -07:00
parent a80d512570
commit bc94a5cb59
4 changed files with 39 additions and 6 deletions

View File

@ -97,6 +97,7 @@ ECDSA.prototype.sig2pubkey = function() {
var Q = R.mul(s).add(G.mul(eNeg)).mul(rInv);
var pubkey = new Pubkey(Q);
pubkey.compressed = this.sig.compressed;
pubkey.validate();
return pubkey;
@ -156,7 +157,7 @@ ECDSA.prototype.sign = function() {
var s = k.invm(N).mul(e.add(d.mul(r))).mod(N);
} while (r.cmp(0) <= 0 || s.cmp(0) <= 0);
this.sig = new Signature(r, s);
this.sig = new Signature(r, s, undefined, this.key.pubkey.compressed);
return this.sig;
};

View File

@ -65,7 +65,7 @@ Message.prototype.verify = function() {
return this;
}
var address = Address().fromPubkey(ecdsa.key.pubkey);
var address = Address().fromPubkey(ecdsa.key.pubkey, undefined, this.sig.compressed);
//TODO: what if livenet/testnet mismatch?
if (address.hashbuf.toString('hex') === this.address.hashbuf.toString('hex'))
this.verified = true;

View File

@ -2,17 +2,25 @@ var BN = require('./bn');
var Point = require('./point');
var Pubkey = require('./pubkey');
var Signature = function Signature(r, s, i) {
var Signature = function Signature(r, s, i, compressed) {
if (!(this instanceof Signature))
return new Signature(r, s, i);
return new Signature(r, s, i, compressed);
this.r = r;
this.s = s;
this.i = i; //public key recovery parameter in range [0, 3]
this.compressed = compressed;
};
Signature.prototype.fromCompact = function(buf) {
var compressed = true;
if (i < 0) {
var compressed = false;
i = i + 4;
}
var i = buf.slice(0, 1)[0] - 27 - 4; //TODO: handle uncompressed pubkeys
var b2 = buf.slice(1, 33);
var b3 = buf.slice(33, 65);
@ -23,6 +31,7 @@ Signature.prototype.fromCompact = function(buf) {
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);
@ -102,12 +111,17 @@ Signature.parseDER = function(buf) {
return obj;
};
Signature.prototype.toCompact = function(i) {
Signature.prototype.toCompact = function(i, compressed) {
i = typeof i === 'number' ? i : this.i;
compressed = typeof compressed === 'boolean' ? compressed : this.compressed;
if (!(i === 0 || i === 1 || i === 2 || i === 3))
throw new Error('i must be equal to 0, 1, 2, or 3');
var b1 = new Buffer([i + 27 + 4]); //TODO: handle uncompressed pubkeys
var val = i + 27 + 4;
if (compressed === false)
val = val - 4;
var b1 = new Buffer([val]);
var b2 = this.r.toBuffer({size: 32});
var b3 = this.s.toBuffer({size: 32});
return Buffer.concat([b1, b2, b3]);

View File

@ -56,6 +56,24 @@ describe('Message', function() {
sigbuf.length.should.equal(1 + 32 + 32);
});
it('should sign with a compressed pubkey', function() {
var key = Key().fromRandom();
key.pubkey.compressed = true;
var sigstr = Message.sign(messagebuf, key);
var sigbuf = new Buffer(sigstr, 'base64');
sigbuf[0].should.be.above(27 + 4 - 1);
sigbuf[0].should.be.below(27 + 4 + 4 - 1);
});
it('should sign with an uncompressed pubkey', function() {
var key = Key().fromRandom();
key.pubkey.compressed = false;
var sigstr = Message.sign(messagebuf, key);
var sigbuf = new Buffer(sigstr, 'base64');
sigbuf[0].should.be.above(27 - 1);
sigbuf[0].should.be.below(27 + 4 - 1);
});
});
describe('@verify', function() {