Last active
June 27, 2018 23:57
-
-
Save hthetiot/f17fcefcaf7dd8cf0b17b41ca2fb1400 to your computer and use it in GitHub Desktop.
Diffie Hellman JavaScript
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment