Ryan X. Charles
11 years ago
9 changed files with 255 additions and 48 deletions
@ -0,0 +1,92 @@ |
|||
var bn = require('./bn'); |
|||
var point = require('./point'); |
|||
var Signature = require('./signature'); |
|||
var Privkey = require('./privkey'); |
|||
var Pubkey = require('./pubkey'); |
|||
var Random = require('./random'); |
|||
|
|||
var ECDSA = function(hash, key, sig, k) { |
|||
this.hash = hash; |
|||
this.key = key; |
|||
this.sig = sig; |
|||
this.k = k; |
|||
}; |
|||
|
|||
ECDSA.prototype.sigError = function() { |
|||
if (!Buffer.isBuffer(this.hash) || this.hash.length !== 32) |
|||
return 'Invalid hash'; |
|||
|
|||
try { |
|||
this.key.pubkey.validate(); |
|||
} catch (e) { |
|||
return 'Invalid pubkey: ' + e; |
|||
}; |
|||
|
|||
var r = this.sig.r; |
|||
var s = this.sig.s; |
|||
if (!(r.gt(0) && r.lt(point.getN())) |
|||
|| !(s.gt(0) && s.lt(point.getN()))) |
|||
return 'r and s not in range'; |
|||
|
|||
var e = bn.fromBuffer(this.hash); |
|||
var n = point.getN(); |
|||
var sinv = s.invm(n); |
|||
var u1 = sinv.mul(e).mod(n); |
|||
var u2 = sinv.mul(r).mod(n); |
|||
|
|||
var p = point.getG().mulAdd(u1, this.key.pubkey.p, u2); |
|||
if (p.isInfinity()) |
|||
return 'p is infinity'; |
|||
|
|||
if (!(p.getX().mod(n).cmp(r) === 0)) |
|||
return 'Invalid signature'; |
|||
else |
|||
return false; |
|||
}; |
|||
|
|||
ECDSA.prototype.randomK = function() { |
|||
var N = point.getN(); |
|||
var k; |
|||
do { |
|||
k = bn.fromBuffer(Random.getRandomBuffer(32)); |
|||
} while (!(k.lt(N) && k.gt(0))); |
|||
this.k = k; |
|||
return this; |
|||
}; |
|||
|
|||
ECDSA.prototype.sign = function() { |
|||
var hash = this.hash; |
|||
var privkey = this.key.privkey; |
|||
var k = this.k; |
|||
var d = privkey.n; |
|||
|
|||
if (!hash || !privkey || !k || !d) |
|||
throw new Error('ecdsa: invalid parameters'); |
|||
|
|||
var N = point.getN(); |
|||
var G = point.getG(); |
|||
var e = bn(hash); |
|||
|
|||
do { |
|||
var Q = G.mul(k); |
|||
var r = Q.x.mod(N); |
|||
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); |
|||
return this.sig; |
|||
}; |
|||
|
|||
ECDSA.prototype.signRandomK = function() { |
|||
var k = this.randomK(); |
|||
return this.sign(); |
|||
}; |
|||
|
|||
ECDSA.prototype.verify = function() { |
|||
if (!this.sigError()) |
|||
return true; |
|||
else |
|||
return false; |
|||
}; |
|||
|
|||
module.exports = ECDSA; |
@ -0,0 +1,41 @@ |
|||
var ECDSA = require('../lib/ecdsa'); |
|||
var Hash = require('../lib/hash'); |
|||
var Key = require('../lib/key'); |
|||
var Privkey = require('../lib/privkey'); |
|||
var Pubkey = require('../lib/pubkey'); |
|||
var bn = require('../lib/bn'); |
|||
var point = require('../lib/point'); |
|||
var should = require('chai').should(); |
|||
|
|||
describe("ecdsa", function() { |
|||
|
|||
it('should create a blank ecdsa', function() { |
|||
var ecdsa = new ECDSA(); |
|||
}); |
|||
|
|||
var ecdsa = new ECDSA(); |
|||
ecdsa.hash = Hash.sha256(new Buffer('test data')); |
|||
ecdsa.key = new Key(); |
|||
ecdsa.key.privkey = new Privkey(bn.fromBuffer(new Buffer('fee0a1f7afebf9d2a5a80c0c98a31c709681cce195cbcd06342b517970c0be1e', 'hex'))); |
|||
ecdsa.key.pubkey = new Pubkey(point(bn.fromBuffer(new Buffer('ac242d242d23be966085a2b2b893d989f824e06c9ad0395a8a52f055ba39abb2', 'hex')), |
|||
bn.fromBuffer(new Buffer('4836ab292c105a711ed10fcfd30999c31ff7c02456147747e03e739ad527c380', 'hex')))); |
|||
|
|||
describe('#signRandomK', function() { |
|||
|
|||
it('should produce a signature', function() { |
|||
ecdsa.signRandomK(); |
|||
should.exist(ecdsa.sig); |
|||
}); |
|||
|
|||
}); |
|||
|
|||
describe('#verify', function() { |
|||
|
|||
it('should verify a signature that was just signed', function() { |
|||
ecdsa.signRandomK(); |
|||
ecdsa.verify().should.equal(true); |
|||
}); |
|||
|
|||
}); |
|||
|
|||
}); |
Loading…
Reference in new issue