WhatsApp mobile messaging app in the firing line again over cryptographic blunder

wa-250

Popular mobile messaging software WhatsApp is in the firing line again for another security SNAFU.

The company has been in hot water before for undercooking its cryptography and overcooking its data collection.

As Naked Security writer Chester Wisniewski wrote in January 2013, the company was investigated in Canada and The Netherlands for grabbing hold of too much data from your address book when you joined the service, and for retaining the data for too long. (Indefinitely, in fact.)

The company also got a roasting for poor cryptographic practices, apparently generating cryptographic keys from data such as your mobile phone’s IMEI (International Mobile Equipment Identity) number or your network MAC (Media Access Code) address.

Your IMEI is burned into mobile phone by the manufacturer, and although it isn’t supposed to be public knowledge, it is at least occasionally broadcast in cleartext by your phone.

In particular: you don’t get to choose your own IMEI; it can’t be considered a secret; and you can’t change it (short of buying a new device).

In other words, using your IMEI as a cryptographic key is a bit like using your passport number or Social Security Number as a password: the wrong way to do it.

Similarly, MAC addresses are loaded into into your network card at manufacture, and are even less suitable as passwords.

MACs are supposed to be publicly visible – every network packet you send out has your MAC in it, and anyone who can sniff your traffic on its first hop is supposed to be able to see it.

→ Learn why MAC addresses are unsuitable as security tokens in our Busting wireless security myths video, which you will find at the bottom of this article.

WhatsApp did the right thing, and re-worked its encryption once these problems were pointed out.

Indeed, the company officially states that “WhatsApp communication between your phone and our server is fully encrypted.”

But Dutch mathematics and computer science student Thijs Alkemade has recently revealed that WhatsApp still hasn’t got it quite right.

In a delightfully clear and concise article, he has explained how WhatsApp went wrong.

Very loosely explained: WhatsApp generates a session key, uses it to initialise a stream cipher, and then uses the same cipher stream for outgoing and incoming messages.

(WhatsApp also uses the RC4 cipher, which is known to have cryptographic flaws, and shouldn’t be used for new applications. Better alternatives are available.)

“This,” as a Canadian friend of mine would put it, “will not do.”

The reason is simple: a stream cipher works as a pseudorandom number generator, emitting an unpredictable string of bytes that you XOR with the plaintext to encrypt.

In other words, you mustn’t use the same string of bytes to encrypt anything else, because that would make it predictable, and that is a cryptographic disaster.

A stream cipher works like a pseudo one time pad, a cryptosystem that relies on a string of hardware random numbers to create an unbreakable cipher if and only if the pad is used just once.

Here’s the problem.

Your message Y, outbound from your device, becomes Y XOR K.

My message M, inbound to your device, becomes M XOR K.

You can see where this is going, if you remember the “rules” of XOR, namely:

K XOR K = 0
A XOR 0 = A
(A XOR B) XOR C = A XOR (B XOR C)
A XOR B XOR C = A XOR C XOR B = C XOR A XOR B, etc. 

(Like + and ×, order doesn't matter when you XOR.)

Now, the reason for encrypting WhatsApp messages is so that if someone sniffs them, it doesn’t matter: they end up with shredded cabbage.

So, let me sniff that shredded cabbage, and show you that in this case, it matters very much indeed.

I XOR the two encrypted messages together:

(Y XOR K) XOR (M XOR K) -> Y XOR K XOR M XOR K
                         = Y XOR M XOR K XOR K
                         = Y XOR M XOR 0
                         = Y XOR M

The key has been cancelled out! Eradicated completely!

Now, assuming that I know M (maybe I sent it) or can guess it (because it contains boilerplate), I can do this:

(Y XOR M) XOR M  -> Y XOR M XOR M
                  = Y XOR 0
                  = Y

Oops: Y is your message, free and clear.

Even if I only know some of M, I can nevertheless recover the corresponding parts of Y, which is not what you want.

What to do

Here’s some advice, for users and programmers alike:

  • Stop using WhatsApp until it’s fixed.
  • Use WhatsApp only for messages you are happy to be considered public.
  • Don’t use IMEIs and MACs as cryptographic key material.
  • Don’t use RC4 any more. Choose something else.
  • Don’t try to roll your own cryptography.

Alkemade suggests that WhatsApp should simply use Transaction Layer Security, or TLS (what used to be SSL, the same end-to-end encryption used by secure websites).

Why reinvent a square wheel when there’s a well-known and well-studied round one you can roll out instead?