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.

107 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;