A friend of mine asked me how OTR can guarantee that we're not MITM'ed, and I thought that maybe she was not the only one wondering about this crypto-powered black-magic, so I wrote this small blogpost.

Since not everyone is well versed into mathematics or computer science, every explanation will have two parts: an "explain me like I'm five" one, and a more mathematical one. As usual in cryptography, our protagonists will be Alice and Bob who're trying to communicate together, while Eve will try to eavesdrop on them.

To perform mutual-authentication, OTR uses something called the Social Millionaire's Protocol (SMP).
It's based on Yao's Millionaires' Problem,
which was proposed by *Andrew C. Yao*, in 1982.

Two millionaires wish to know who is richer; however, they do not want to find out inadvertently any additional information about each other’s wealth. How can they carry out such a conversation?

# Diffie-hellman

The solution to this problem used by OTR is using the
Diffie-Hellman key exchange (DH) as a primitive.
As you may have guessed, this scheme was invented by Whitfield *Diffie* and Martin *Hellman*,
in 1976. It allows two parties that have no prior knowledge
of each other to establish a shared secret, over an insecure communication channel. This primitive
is not authenticated, meaning that it's vulnerable to MITM.

Wikipedia has an awesome picture to explain this process with paint:

And now some mathematics:

Let *p* be a prime number (A prime number is greater than *1*, and can only be divided by itself or by *1*),
and *g* a primitive root modulo p.

Primitive root modulo *p* means that every number coprime (Coprimes numbers have no common divisors except 1.)
to *p* is congruent to a power of *g* modulo *n*. This can be summarized as: *g primitive root modulo p ⇔ ∀n, n⊥p, ∃k, g ^{k} ≡ n (mod p)*

In OTR, both p and g are fixed: the first one to a 1536-bit prime, and the later is equal to 2. This is how it works:

- Alice is choosing a random number
*a*, and she sends over an insecure channel*A = g*to Bob.^{a}mod p - Bob is choosing a random number
*b*, and he sends over an insecure channel*B = g*to Alice.^{b}mod p - Alice computes
*s = B*.^{a}mod p - Bob computes
*s = A*.^{b}mod p

Now Alice and Bob are sharing the same secret *s*.

When numbers are big enough, given *g*, *p*, *g ^{b} mod p* and

*g*, it's

^{a}mod p**really super hard**to find

*a*or

*b*, even for super-computers. This is knows as the discrete logarithm problem.

Ok, now we have a way to create a shared secret, but we're still vulnerable to MITM.

# Socialist millionaire protocol

You may wonder how we could use the SMP to establish authentication without being vulnerable to MITM. Think of the wealth amount as a shared secret : You can check if both of you are knowing it, without disclosing it. If someone is trying to MITM you, she'll have to guess this amount.

Someone else already came up with a great explanation of the SMP, and I didn't managed to find something better.

So let's jump to the mathematical side, straight from OTR 3.4 specification:

- Alice
- Picks random exponents
*a*_{2}and a_{3} - Sends Bob
*g*_{2a}= g_{1}^{a2}and g_{3a}= g_{1}^{a3}

- Picks random exponents
- Bob
- Picks random exponents
*b*_{2}and b_{3} - Computes
*g*_{2b}= g_{1}^{b2}and g_{3b}= g_{1}^{b3} - Computes
*g*_{2}= g_{2a}^{b2}and g_{3}= g_{3a}^{b3} - Picks random exponent
*r* - Computes
*P*_{b}= g_{3}^{r}and Q_{b}= g_{1}^{r}g_{2}^{y} - Sends Alice
*g*_{2b}, g_{3b}, P_{b}and Q_{b}

- Picks random exponents
- Alice
- Computes
*g*_{2}= g_{2b}^{a2}and g_{3}= g_{3b}^{a3} - Picks random exponent
*s* - Computes
*P*_{a}= g_{3}^{s}and Q_{a}= g_{1}^{s}g_{2}^{x} - Computes
*R*_{a}= (Q_{a}/ Q_{b})^{a3} - Sends Bob
*P*_{a}, Q_{a}and R_{a}

- Computes
- Bob
- Computes
*R*_{b}= (Q_{a}/ Q_{b})^{b3} - Computes
*R*_{ab}= R_{a}^{b3} - Checks whether
*R*_{ab}== (P_{a}/ P_{b}) - Sends Alice
*R*_{b}

- Computes
- Alice
- Computes
*R*_{ab}= R_{b}^{a3} - Checks whether
*R*_{ab}== (P_{a}/ P_{b})

- Computes

## Proof

*R _{ab}
= R_{a}^{b3}
= (Q_{a} / Q_{b}) ^{a3·b3}
= (g_{1}^{s - r} · g_{2}^{x - y}) ^{a3}·^{b3}
= g_{1}^{a3·b3·(s - r)} · g_{2}^{(x - y)·a3·b3}*

*P _{a} / P_{b}
= g_{3}^{s} / g_{3}^{r}
= g_{3}^{s - r}
= g_{3a}^{b3·(s - r)}
= g_{1}^{a3·b3·(s - r)}*

This means that

*g _{2}^{a3}·^{b3·(x - y)} = 1*

Since *g _{2}^{a3}·^{b3}* is a random number different from 1,
the only solution is that

*x - y = 0*, meaning that

*x = y*.

Thanks to the discrete logarithm problem, an attacker eavesdropping on the connection wouldn't be able to guess the secret. If she was trying to MITM with the wrong secret, the final check will fail.

## The common secret

When Alice and Bob are initiating an OTR communication,
they are first creating a shared secret with Diffie-Hellman,
then are doing a mutual authentication. This process is named
Authenticated Key Exchange (AKE), and produces the shared secret *s*.

Don't be fooled by the term *mutual authentication*, here, we're speaking of *keys*,
not persons: the communication is secure between those two keys, but at this point,
Alice and Bob can't be sure (Unless they know each other fingerprints.) that they
are not MITM'ed.

For OTR, the secret *x* (or *y* if you're Bob) is composed of:
*SHA256(0x01|initiator_fingerprint|responder_fingerprint|session_id|secret)*,
with *sessions_id* equals to *SHA256(0x00|s)*.

Why is the secret *x* (or *y*) so complicated? Because this ensures that you're doing the authentication
with the *right* fingerprints, in the *right* session.

If you have used a decent OTR client, you'll noticed that you can either use a *shared secret*,
or ask a question. When you're choosing the later, the answer to the question is used
as the shared secret, while the question is transmitted along with the first message.
You can also of course manually verify the fingerprint, but this is less convenient.

# Conclusion

If hope that now you understand how the magic authentication of OTR is working, and that you're eager to know more about this wonderful protocol by reading its specification, or at least, to use it for your IM communications.

By the way, if you know some C, feel free to help us improving libotr, the reference implementation of OTR ;)