Skip to content

Instantly share code, notes, and snippets.

@hthetiot
Last active June 27, 2018 23:57
Show Gist options
  • Save hthetiot/f17fcefcaf7dd8cf0b17b41ca2fb1400 to your computer and use it in GitHub Desktop.
Save hthetiot/f17fcefcaf7dd8cf0b17b41ca2fb1400 to your computer and use it in GitHub Desktop.
Diffie Hellman JavaScript
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