Pitfalls of rolling your own E2EE protcol

Pitfalls of rolling your own E2EE protcol


UPDATE 2021-08-14: Please read the updated post on https://pwn.recipes/posts/roll-your-own-e2ee-protocol/. It contains all of the info in this one and more.

UPDATE 2021-08-05: The author of the app answered twice:
https://news.ycombinator.com/item?id=28071458
https://news.ycombinator.com/item?id=28074309
I haven't had time to respond to him, yet.

Original post:

(There is a TL;DR at the bottom.)

In a recent HN thread "My small revenge on Apple"[1], Javier Anton talked about their app, which the website[2] claims is end-to-end encrypted. There is no source available, so all the below is based on a short reverse engineering session of the android app. It is very possible that something was overlooked in this analysis (positively or negatively). This is also not meant as an attack on the author. Instead, this should highlight some of the pitfalls of rolling your own encryption protocol.

The part of the protocol seen in this short session works like this: when two parties want to chat, the app generates a random encryption key and encrypts that with the RSA key of the other party. This way, the server can't decrypt the chat key and thus can't read your messages (in theory).

The RSA key generation happens on the device, which is good, and uses SecureRandom which is also good. The key size is 2048 bits, which the BSI recommends[3] to use only until 2022. Hopefully the author plans to upgrade everyone's keys to 3kbit next year some time.

The ChatKey is generated a bit differently:

It looks like the ChatKey's are generated using java.util.Random(), which in the library the author uses is described as[4]:

public Random() 
Creates a new random number generator. Its seed is initialized to a value based on the current time: public Random() { this(System.currentTimeMillis()); }

On Android, the standard Random is not entirely[5] based on current system time, but it does not seem like Codename One uses that. The documentation says it's purely time-based.

Even if it were random, though, successive outputs of a non-CSPRNG typically reveal the internal state of the RNG. That's why one just doesn't use this for key generation. In this case, the RNG is reinitialized for every key generation run. Depending on the RNG it uses (again, non-CSPRNG does not make guarantees here), assuming a few starting bytes might allow you to determine what later outputs have to be, reducing the key's strength significantly because there are only so many possible starting sequences. If the RNG's seed wasn't weak already.

While there is a Windows client, the app's website says iOS and Android are the only platforms that support end-to-end encrypted instant messaging.

Finally, it does not appear possible to verify keys. A chat was started with a random stranger and no method was found to verify either the RSA key or the ChatKey. This means that you have to trust the server to give you the right RSA key; the server could just give you a different key and intercept the connection and the average user could never tell.

Open questions include whether:

 - iOS has the same issues

 - chat keys are ever changed or when (forward secrecy)

 - you can verify RSA fingerprints out of bounds

 - it's legal to have a directory of all registered users and email addresses accessible to all users


TL;DR:

- Time-based encryption key generation

- Non-cryptographically secure key generator

- RSA key length is considered insecure in 2022 already and protects *everything*

- You trust the server because you can't seem to verify the encryption keys in-person (or at least out-of-band, like via PGP or Signal)

   - Thus it's not end-to-end encryption; at best, it's trust-on-first-use


If you're going to use a closed-source E2EE chat application, you might as well use WhatsApp. At least there you know that the protocol itself is not the issue.


[1]: https://news.ycombinator.com/item?id=28058698

[2]: https://groupsapp.online

[3]: https://www.keylength.com/en/8/

[4]: https://codenameone.com/javadoc/index.html?java/util/Random.html

[5]: https://android.googlesource.com/platform/dalvik/+/f87ab9616697b8bae08c5e8007cbdd0039a1f8ce/libcore/luni/src/main/java/java/util/Random.java#60


Report Page