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