## Diffie-Hellman Test

Proof of concept that you can do a Diffie-Hellman key exchange between a browser running JavaScript and a web server running C.

Diffie-Hellman key exchange is a way for two parties to agree on a shared secret key without letting any hypothetical eavesdroppers know what the key is. It works like this:

• Both sides agree beforehand on two parameters, a modulus p and a base g. p should be a large "safe prime" number, 2048 bits or so. g should be a primitive root mod p; it does not need to be large, in fact for many moduli using g = 2 works fine.
• The client side - the JavaScript code running in the web browser - generates a random int a in [0..p).
• The client computes A = ga mod p and sends that to the server.
• The server generates a random int b in [0..p).
• The server computes B = gb mod p and sends that back to the client.
• The client computes s = Ba mod p.
• The server computes s = Ab mod p.

Now both parties have the same shared secret number s.

Doing the calculations requires arbitrary-precision arithmetic, a.k.a. "bignums". In C this is widely available as part of the libcrypto library. In JavaScript, there are a few packages available. This demo uses biginteger.js by Matthew Crumley.

Let's try it out. Start by choosing a group, the p&g pair. The groups in the selector come from RFC2409 and RFC3526 and are recommended for use with DH. Or you can paste in your own numbers if you know what you're doing. There are trade-offs in choosing a group to use - use one of the standard ones and maybe the NSA has pre-computed an attack table for it; make your own group and maybe you'll get a detail wrong.

p:
g:

Now, phase 1: choose a random number a and compute A = ga mod p.

a:
A:

Phase 2: choose a random number b and compute B = gb mod p; also use the A from phase 1 to compute s = Ab mod p.

b:
B:
A:
s:

Phase 3: use the a from phase 1 and the B from phase 2 to compute s = Ba mod p.

a:
B:
s:

Now you have s two different ways.

You can also run the same calculations on a Unix system if you have one handy. Fetch dhtest.c and compile it like so:

`cc -Wall -I/usr/local/include dhtest.c -L/usr/local/lib -lcrypto -o dhtest`

The dhtest program can do all three phases of the DH exchange. Normally the server side would do phase 2, but let's run it on phase 3 so we can compare results. Here's the command with the same numbers as above:

`./dhtest -3    `

It should give you the same value for s that you got above. This demonstrates that the JavaScript version running in the browser and the C version running on the server can interoperate.

Now that we've established that it's possible, is DH in the browser a good idea? Probably not.

• It's slow. The smallest key, only 768 bits, takes about five seconds for a key exchange. A more reasonable 2048-bit key takes about a minute.
• It's inherently insecure. Any other code running in the same JavaScript environment can inspect and modify any part of your code.
• It's unnecessary. Just use SSL, which is already doing key exchange much better and faster than this.
• It's likely to be obsolete soon. As soon as the Web API standards folks get their act together on the Web Cryptography API, a do-it-yourself version will be unnecessary.

Check out this 2011 blog post by Thomas Ptacek or this 2013 blog post by Tony Arcieri for lots more reasons.

In summary: cool experiment, not really useful.

ACME Labs / DH Test