| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164 | 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);  }}
 |