const BN = require('bn.js'); var USE_BINARY = true; var UNIQUE_PRIME = true; var MIN_INTEGER = 100; var MAX_INTEGER = 40000; //Number.MAX_SAFE_INTEGER; // https://jsperf.com/prime-numbers/7 function number(p) { return USE_BINARY ? new BN(p, 16) : parseInt(p, 16) } function pow(a, b) { process.stdout.write('+'); return USE_BINARY ? a.pow(b) : Math.pow(a, b).toFixed(3); } function mod(a, b) { process.stdout.write('+'); return USE_BINARY ? a.mod(b) : (a % b).toFixed(3); } function equal(a, b) { return USE_BINARY ? a.cmp(b) === 0 : a === b; } function getRandomInt(min, max) { min = min || 2; max = max || Number.MAX_SAFE_INTEGER; return Math.floor(Math.random() * (max - min + 1)) + min; } function getRandomPrime(min, max) { var p; do { //process.stdout.write('.'); p = getRandomInt(min, max); } while( isPrime(p) === false || ( UNIQUE_PRIME && getRandomPrime.cache.hasOwnProperty(p) ) ); process.stdout.write('*'); getRandomPrime.cache[p] = true; return number(p); } getRandomPrime.cache = {}; function isPrime(num) { if (isPrime.cache.hasOwnProperty(num)) { return isPrime.cache[num]; } // Everything but 1 can be prime var prime = num !== 1; for (var i = 2; i < num; i++) { if (num % i === 0) { prime = false; break; } } isPrime.cache[num] = prime; return prime; }; isPrime.cache = {}; function makeKeyPair(min, max) { function createPublicKey(max) { return getRandomPrime(min, max - 1) } // Setup Alice var alice = { publicKey: null, privateKey: null }; var p = createPublicKey(max); var a = getRandomPrime(min, p); // < (p - 1) alice.publicKey = p; alice.privateKey = a; // Setup Bob var bob = { publicKey: null, privateKey: null }; var g = createPublicKey(max); var b = getRandomPrime(min, g); // < (g - 1) bob.publicKey = g; bob.privateKey = b; // Bob send g to Alice alice.remotePublicKey = g; // Alice forge A based g var A = mod(pow(g, a), p); // Alice share A to Bob bob.publicToken = A; // Alice send A and p bob.remotePublicKey = p; // Alice forge B based p var B = mod(pow(g, b), p); // Alice share B to Alice alice.publicToken = B; // Bob then forge aSecret based on A, b and p var bSecret = mod(pow(A, b), p); bob.sharedSecret = bSecret; // Alice then forge aSecret based on B, a and p var aSecret = mod(pow(B, a), p); alice.sharedSecret = aSecret; // Alice and Bob share the same token. var isValid = equal(aSecret, bSecret); return { alice: alice, bob: bob, result: isValid }; } do { var pair = makeKeyPair(MIN_INTEGER, MAX_INTEGER) if (pair.result === false) { console.log('FAILED', pair); break; } else { process.stdout.write('_'); } } while(1);