You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
106 lines
2.7 KiB
106 lines
2.7 KiB
var bignum = require('bignum');
|
|
var Point = require('./Point');
|
|
var SecureRandom = require('./SecureRandom');
|
|
var Key = function() {}
|
|
|
|
Key.parseDERsig = function(sig) {
|
|
if (!Buffer.isBuffer(sig))
|
|
throw new Error('DER formatted signature should be a buffer');
|
|
|
|
var header = sig[0];
|
|
|
|
if (header !== 0x30)
|
|
throw new Error('Header byte should be 0x30');
|
|
|
|
var length = sig[1];
|
|
if (length !== sig.slice(2).length)
|
|
throw new Error('Length byte should length of what follows');
|
|
|
|
var rheader = sig[2 + 0];
|
|
if (rheader !== 0x02)
|
|
throw new Error('Integer byte for r should be 0x02');
|
|
|
|
var rlength = sig[2 + 1];
|
|
var rbuf = sig.slice(2 + 2, 2 + 2 + rlength);
|
|
var r = bignum.fromBuffer(rbuf);
|
|
var rneg = sig[2 + 1 + 1] === 0x00 ? true : false;
|
|
if (rlength !== rbuf.length)
|
|
throw new Error('Length of r incorrect');
|
|
|
|
var sheader = sig[2 + 2 + rlength + 0];
|
|
if (sheader !== 0x02)
|
|
throw new Error('Integer byte for s should be 0x02');
|
|
|
|
var slength = sig[2 + 2 + rlength + 1];
|
|
var sbuf = sig.slice(2 + 2 + rlength + 2, 2 + 2 + rlength + 2 + slength);
|
|
var s = bignum.fromBuffer(sbuf);
|
|
var sneg = sig[2 + 2 + rlength + 2 + 2] === 0x00 ? true : false;
|
|
if (slength !== sbuf.length)
|
|
throw new Error('Length of s incorrect');
|
|
|
|
var sumlength = 2 + 2 + rlength + 2 + slength;
|
|
if (length !== sumlength - 2)
|
|
throw new Error('Length of signature incorrect');
|
|
|
|
|
|
var obj = {
|
|
header: header,
|
|
length: length,
|
|
rheader: rheader,
|
|
rlength: rlength,
|
|
rneg: rneg,
|
|
rbuf: rbuf,
|
|
r: r,
|
|
sheader: sheader,
|
|
slength: slength,
|
|
sneg: sneg,
|
|
sbuf: sbuf,
|
|
s: s
|
|
};
|
|
|
|
return obj;
|
|
};
|
|
|
|
Key.rs2DER = function(r, s) {
|
|
var rnbuf = r.toBuffer();
|
|
var snbuf = s.toBuffer();
|
|
|
|
var rneg = rnbuf[0] & 0x80 ? true : false;
|
|
var sneg = snbuf[0] & 0x80 ? true : false;
|
|
|
|
var rbuf = rneg ? Buffer.concat([new Buffer([0x00]), rnbuf]) : rnbuf;
|
|
var sbuf = sneg ? Buffer.concat([new Buffer([0x00]), snbuf]) : snbuf;
|
|
|
|
var length = 2 + rbuf.length + 2 + sbuf.length;
|
|
var rlength = rbuf.length;
|
|
var slength = sbuf.length;
|
|
var rheader = 0x02;
|
|
var sheader = 0x02;
|
|
var header = 0x30;
|
|
|
|
var der = Buffer.concat([new Buffer([header, length, rheader, rlength]), rbuf, new Buffer([sheader, slength]), sbuf]);
|
|
return der;
|
|
};
|
|
|
|
Key.sign = function(hash, priv, k) {
|
|
var d = priv;
|
|
var n = Point.getN();
|
|
var e = new bignum(hash);
|
|
|
|
do {
|
|
var k = k || Key.genk();
|
|
var G = Point.getG();
|
|
var Q = Point.multiply(G, k);
|
|
var r = Q.x.mod(n);
|
|
var s = k.invm(n).mul(e.add(d.mul(r))).mod(n);
|
|
} while (r.cmp(new bignum(0)) <= 0 || s.cmp(new bignum(0)) <= 0);
|
|
|
|
return {r: r, s: s};
|
|
};
|
|
|
|
Key.genk = function() {
|
|
//TODO: account for when >= n
|
|
return new bignum(SecureRandom.getRandomBuffer(8));
|
|
};
|
|
|
|
module.exports = Key;
|
|
|