This post presents the Diffie-Hellman Key Exchange (DHKE) - an important part of today's practical cryptography. Whenever you're accessing an HTTPS website, it's very likely that your browser and the server negotiated a shared secret key using the DHKE under the hood.

## Mathematical prerequisites

The understand the math behind DHKE, you should be familiar with basic *group
theory*. A group is a set with a binary operation, such that any two items in
the set combined with the operation produce another item in the set, the
operation is associative, the set has an identity element w.r.t the operation
and each set element has an inverse.

The group we're most interested in for the sake of understanding Diffie Hellman
is - the positive integers that are relatively prime
to *p*, with the "multiplication modulo *p*" operation (another common notation
for this group is ). This is a finite group.
By definition, its cardinality is , where is
Euler's totient function.

As an example, . The cardinality of this group is . We can multiply members of the group modulo 9 to get other elements of the group: , etc.

For a prime *p*, the group contains all the integers from 1 to *p-1*
and its cardinality is *p-1*.

### Cyclic groups

Given a group *G* with the operator , we define the **order**
of an element *g* in the group - *ord(g)* - as the smallest positive integer
*k* such that:

Where 1 is the identity element of *G*. Note that we use the exponent notation
for convenience, even though is not necessarily a
multiplication - this would work for any group. For example, in the group
shown above, *ord(8)* is 2, and *ord(2)* is 6.

A group *G* which contains an element *a* with the maximal order
is called a **cyclic group**. Elements in a
cyclic group that have maximal orders are called *generators* or *primitive
elements*.

These elements can generate all the other elements of the group by repeated
application of the group operation. In other words, given a generator *g*,
every can be expressed as for some *k*.

For example, is cyclic and its primitive elements are 2, 5 and 8.

It can be shown that for a prime *p*, the group is
always cyclic and has primitive elements, though there's
no easy way to find them - we just have to test them one by one. The proof of
this theorem is quite technical, so I'll leave it for another time.

## The Discrete Logarithm Problem

The mathematical problem at the heart of the DHKE is the Discrete Logarithm Problem (DLP). In this discussion I'm going to focus on the DLP in the multiplicative group of integers modulo a prime - , and will mention the general DLP later on.

Given a finite cyclic group with a prime *p*,
a primitive element and another element
, the DLP problem is finding an integer
such that:

We've seen earlier that such an integer must exist because *g* is a primitive
element of the group.

The DLP is hard - no one knows how to solve it efficiently. This doesn't mean that such a solution doesn't exist - it wasn't proven to not exist. In this, DLP is similar to factoring, which is essential for the security of RSA.

## Diffie-Hellman Key Exchange (DHKE)

The protocol starts with a *setup stage*, where the two parties agree on the
parameters *p* and *g* to be used in the rest of the protocol. These parameters
can be entirely public, and are specified in RFCs, such as RFC 7919.

For the main key exchange protocol, let's assume that Alice and Bob want to
compute a shared secret they could later use to send encrypted messages to one
another. They know *p* and *g* already.

**Stage 1**

Alice does:

- Choose a random
- compute

Bob does:

- Choose a random
- compute

These *B*s are Alice's and Bob's public keys, while *b*s are their private
keys. Note that due to the DLP, it's hard to compute *b* from *B*.

**Stage 2**

Alice sends to Bob, while Bob sends to Alice.

**Stage 3**
Now, Bob can compute .

Alice can compute .

These are equal, and serve as a shared key between Alice and Bob. They can now use it to encrypt a strong symmetric cipher key (say, AES-256) and use that to communicate in complete privacy.

## Authenticated DHKE

The basic DHKE protocol, as descibed above, is easily vulnerable to a man-in-the-middle (MITM) attack. When Alice and Bob exchange their public keys in stage 2, nothing guarantees to Alice that the key she received comes from Bob. Eve could place herself between Alice and Bob and set up an exchange with each one of them separately, while making them beleive they are talking to each other. Then she could read all the traffic, while Alice and Bob suspect nothing.

The solution to this problem is to use *authenticated DHKE* instead. The core
protocol remains the same, but when Alice and Bob exchange messages, these
are signed with a strong signature algorithm. For example, Alice and Bob can
use their RSA private keys to sign these messages. Then the MITM attack is
impossible because Eve can't send a message to Bob pretending she's Alice,
without access to Alice's private RSA key.

## Forward secrecy

In the RSA post we've
seen how the RSA algorithm can be used to create a shared secret between two
parties and thus for secret communication. RSA has a serious flaw when used
like that, though. There's a lot of traffic using a single key, which may help
breaking it. Once broken, this key can be used to read *all past* communications
that used the same key.

DHKE, on the other hand, has *forward secrecy*. A new DHKE shared secret is
generated for every session. Breaking this key will expose the secrets of this
session, but won't enable the attacker to read all past correspondence. Such
keys are called *ephemeral*.

You may ask - can't RSA be made ephemeral? Can't we use a "master" RSA key to authenticate the key exchange, and generate a fresh public/private key pair for each communication? Yes, that's absolutely possible, but DHKE is still preferred because it's more efficient. While generating an RSA key pair requires finding two large primes with certain characteristics, generating a new DHKE public key is simply choosing a random integer and computing a single modular exponent - this is much faster.

## Choosing "safe" primes

We've seen before that the *p* and *g* parameters for DHKE are public. How are
these chosen? Can we choose any *p* and *g* and have strong security?

Turns out that the answer is no, due to some interesting math. Algorithms like Index Calculus can be used to crack the DLP in sub-exponential time. It's so powerful that we'll need primes of 1024 bits to have 80-bit security (meaning the equivalent of brute-forcing a 80-bit symmetric key).

When coupled with the Pohlig-Hellman attack, we may get in
trouble. This attack uses the CRT to break
the DLP in time proportional to the *factors* of *|G|* [1]. Note that when *p*
is a prime, *p-1* is composite, so it will end up having some factors. Which
factors? Hard to say, but we want to maximize them. The best way to maximize
them is to pick primes of the form *2q+1*, where *q* is a prime. Then
, and its factors are 2 and *q*. *g* is chosen such that it
generates a sub-group of size *q*, which ensures we have a large prime *|G|*.

Primes of the form *2q+1* are called *safe primes*.

For example, RFC 7919 recommends several parameters, presenting them thus:

```
The hexadecimal representation of p is:
FFFFFFFF FFFFFFFF ADF85458 A2BB4A9A AFDC5620 273D3CF1
D8B9C583 CE2D3695 A9E13641 146433FB CC939DCE 249B3EF9
7D2FE363 630C75D8 F681B202 AEC4617A D3DF1ED5 D5FD6561
2433F51F 5F066ED0 85636555 3DED1AF3 B557135E 7F57C935
984F0C70 E0E68B77 E2A689DA F3EFE872 1DF158A1 36ADE735
30ACCA4F 483A797A BC0AB182 B324FB61 D108A94B B2C8E3FB
B96ADAB7 60D7F468 1D4F42A3 DE394DF4 AE56EDE7 6372BB19
0B07A7C8 EE0A6D70 9E02FCE1 CDF7E2EC C03404CD 28342F61
9172FE9C E98583FF 8E4F1232 EEF28183 C3FE3B1B 4C6FAD73
3BB5FCBC 2EC22005 C58EF183 7D1683B2 C6F34A26 C1B2EFFA
886B4238 611FCFDC DE355B3B 6519035B BC34F4DE F99C0238
61B46FC9 D6E6C907 7AD91D26 91F7F7EE 598CB0FA C186D91C
AEFE1309 85139270 B4130C93 BC437944 F4FD4452 E2D74DD3
64F2E21E 71F54BFF 5CAE82AB 9C9DF69E E86D2BC5 22363A0D
ABC52197 9B0DEADA 1DBF9A42 D5C4484E 0ABCD06B FA53DDEF
3C1B20EE 3FD59D7C 25E41D2B 66C62E37 FFFFFFFF FFFFFFFF
The generator is: g = 2
The group size is: q = (p-1)/2
```

The parameters in this RFC are the only ones approved for the newest TLS standard - version 1.3, which also removes the support for custom groups.

The safety of the primes used for DHKE is not a purely theoretical concern! Real attacks have been (and are probably still being) mounted against unsafe choices. See CVE-2016-0701 for example, and the paper Measuring small subgroup attacks against Diffie-Hellman for more technical details.

## A word on elliptic curves

Elliptic curves are all the rage in cryptography in the past couple of decades, and for a good reason. They provide similar security to the "classical" multiplicative modular groups with much smaller keys. If you're using TLS 1.3, the key exchange protocol will most likely be ECDHE - Elliptic Curve Diffie-Hellman Exchange.

Explaining elliptic curves is a huge topic of its own, so I'll just briefly mention them w.r.t. the material presented in this post.

The beauty of abstract algebra is that you can develop mathematics that will apply in the same way to very different groups. We've seen the DLP defined for multiplicative modular groups, but it can also be defined for different groups.

Elliptic curves are pairs of points which fullfill certain polynomial equations [2], and when set up properly these points can form cyclic groups under certain operations. A DLP can be defined for these groups, and it's as hard to solve as the classical DLP. Much of the math remains the same - generators, subgroups, and so on. DHKE looks the same as well - Alice and Bob both pick a random group member, and compute an "exponent" (repeated application of the group operation), sending it on the wire. They combine their exponents to get a shared secret key, while Eve cannot reconstruct their private exponents from the transmitted information because of the infeasibility of the DLP.

Elliptic curve groups are great because - compared to classical multiplicative modular groups - they are less susceptible to sub-exponential attacks. Therefore, to gain ~128 bits of security (i.e. make attacks equivalent to brute-forcing 128-bit values) we can use a key of size 256 bits (as opposed to 3072 bits for classical DH). This makes cryptographic protocols much faster.

[1] | Specifically, it's proportional to the sizes of the subgroup which the
generator generates. The size of subgroups are related to the factors of
|G|, per Lagrange's Theorem. |

[2] | , which should look familiar from analytic geometry in middle school. |