Snapchat

A full analysis of the Snapchat API and its vulnerabilities can be found at Gibson Security. Steve Gibson and his team analyzed the Snapchat API and found several vulnerabilities. They disclosed their findings to Snapchat with an offer to help them correct the errors. One of the mistakes that Snapchat made was to use a constant symmetric key.

Globally Shared Secret

Each message is encrypted using the Snapchat mobile application. The reason is that, unlike Twitter messages, Snapchat messages should only be read by your friends. So encrypting those messages would seem like adequate protection.

To encrypt the message, Snapchat employed a symmetric key. This is as you would expect, since messages can be quite large, and asymmetric keys can only encrypt messages smaller than themselves.

The problem, however, is that Snapchat used the same symmetric key for every message. Worse yet, that symmetric key was embedded within each mobile app. So to discover the key, an attacker need only decompile the application package.

For Your Eyes Only

To truly encrypt a message for a smal set of people, you need to make sure that only they have the symmetric key. So you should produce a new symmetric key for every message that you send.

But if you produce a symmetric key to send a message, how do you get that symmetric key to the recipients? And how to you ensure that only they can read it? The answer is to have each of the recipients produce an asymmetric key pair. This is a pair of keys, one public and the other private, that can be used to privately share something small, like the symmetric key.

When a user installs the application on a device, the app produces a key pair. It broadcasts the public key to all of the user's friends. The private key never leaves the device. Then, when friends wish to send that user a message, they will generate a new symmetric key, and then encrypt that symmetric key with the user's public key. They send all of these encrypted keys back to their respective recipients, each of whom decrypt it with their private key.

The sender can publish the encrypted message in a common place. It does not need to be encrypted differently for each recipient. They all use the same symmetric key to decrypt the message. But only the intended recipients have this shared key, because only they had the private key necessary to decrypt it.

Trusted Identity

So what prevents an attacker from sending their public key, and tricking a sender into encrypting the shared key for them? Well, to prevent that attack, the server should sign the public keys produced by a user's devices. When they log in, they receive an authentication token. Then, the device sends the server a signing request with that authentication token. The server will sign it with a private key that only it knows.

Now a sender can verify that the public key of their friend actually belongs to that friend. They can validate the server's signature by using its public key. Unlike the shared key, the public key can be embedded within the mobile app. If the signature is valid, then the sender trusts that the recipient had a valid authentication token, and is therefore who they claim to be.

Encryption alone is not enough. A secure protocol considers all of the information that an attacker could obtain. If it's on the wire or in the app package, then assume that the attacker knows it. Always generate a unique symmetric key per message. And then use trusted public keys to exchange those symmetric keys.