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.
|
|
var BN = require('bn.js'); var MillerRabin = require('miller-rabin'); var millerRabin = new MillerRabin(); var TWENTYFOUR = new BN(24); var ELEVEN = new BN(11); var TEN = new BN(10); var THREE = new BN(3); var SEVEN = new BN(7); var primes = require('./generatePrime'); var randomBytes = require('randombytes'); module.exports = DH;
function setPublicKey(pub, enc) { enc = enc || 'utf8'; if (!Buffer.isBuffer(pub)) { pub = new Buffer(pub, enc); } this._pub = new BN(pub); return this; }
function setPrivateKey(priv, enc) { enc = enc || 'utf8'; if (!Buffer.isBuffer(priv)) { priv = new Buffer(priv, enc); } this._priv = new BN(priv); return this; }
var primeCache = {}; function checkPrime(prime, generator) { var gen = generator.toString('hex'); var hex = [gen, prime.toString(16)].join('_'); if (hex in primeCache) { return primeCache[hex]; } var error = 0;
if (prime.isEven() || !primes.simpleSieve || !primes.fermatTest(prime) || !millerRabin.test(prime)) { //not a prime so +1
error += 1;
if (gen === '02' || gen === '05') { // we'd be able to check the generator
// it would fail so +8
error += 8; } else { //we wouldn't be able to test the generator
// so +4
error += 4; } primeCache[hex] = error; return error; } if (!millerRabin.test(prime.shrn(1))) { //not a safe prime
error += 2; } var rem; switch (gen) { case '02': if (prime.mod(TWENTYFOUR).cmp(ELEVEN)) { // unsuidable generator
error += 8; } break; case '05': rem = prime.mod(TEN); if (rem.cmp(THREE) && rem.cmp(SEVEN)) { // prime mod 10 needs to equal 3 or 7
error += 8; } break; default: error += 4; } primeCache[hex] = error; return error; }
function DH(prime, generator, malleable) { this.setGenerator(generator); this.__prime = new BN(prime); this._prime = BN.mont(this.__prime); this._primeLen = prime.length; this._pub = undefined; this._priv = undefined; this._primeCode = undefined; if (malleable) { this.setPublicKey = setPublicKey; this.setPrivateKey = setPrivateKey; } else { this._primeCode = 8; } } Object.defineProperty(DH.prototype, 'verifyError', { enumerable: true, get: function () { if (typeof this._primeCode !== 'number') { this._primeCode = checkPrime(this.__prime, this.__gen); } return this._primeCode; } }); DH.prototype.generateKeys = function () { if (!this._priv) { this._priv = new BN(randomBytes(this._primeLen)); } this._pub = this._gen.toRed(this._prime).redPow(this._priv).fromRed(); return this.getPublicKey(); };
DH.prototype.computeSecret = function (other) { other = new BN(other); other = other.toRed(this._prime); var secret = other.redPow(this._priv).fromRed(); var out = new Buffer(secret.toArray()); var prime = this.getPrime(); if (out.length < prime.length) { var front = new Buffer(prime.length - out.length); front.fill(0); out = Buffer.concat([front, out]); } return out; };
DH.prototype.getPublicKey = function getPublicKey(enc) { return formatReturnValue(this._pub, enc); };
DH.prototype.getPrivateKey = function getPrivateKey(enc) { return formatReturnValue(this._priv, enc); };
DH.prototype.getPrime = function (enc) { return formatReturnValue(this.__prime, enc); };
DH.prototype.getGenerator = function (enc) { return formatReturnValue(this._gen, enc); };
DH.prototype.setGenerator = function (gen, enc) { enc = enc || 'utf8'; if (!Buffer.isBuffer(gen)) { gen = new Buffer(gen, enc); } this.__gen = gen; this._gen = new BN(gen); return this; };
function formatReturnValue(bn, enc) { var buf = new Buffer(bn.toArray()); if (!enc) { return buf; } else { return buf.toString(enc); } }
|