Threema

Threema is a private messaging app and a competitor to Signal. However, it does leak metadata. In this article I discuss exactly what Threema leaks, and why.


What is a metadata leak?

Metadata leaks are when your messaging app includes metadata in a way that's not encrypted end-to-end. This includes the dates and times you send messages, who you send them to, how frequently you send messages, and more. Many messengers allow you to set status messages and profile pictures. These are not encrypted, and are thus leaked. The issue with metadata leaks is they can fairly easily reveal sensitive information, even when you don't expect them to.

Threema's merits

Threema's cryptographic design is solid. It uses the NaCl cryptography library in a standard way. It uses a very simple, easy-to-verify protocol. It also allows anonymous users, which prevents people from having to reveal information about themselves.

Threema's Achilles' heel

The major issue with Threema is that it leaks metadata:

To understand how Threema leaks metadata, and to whom, it is important to understand the basics of how Threema works. Threema has 2 encryption layers:

Threema uses the following scheme:

void send_message(message, recipient){
  send_to_server(
    transport_encrypt(
        e2ee_encrypt(message, recipient),
      recipient)
  );
}

The transport layer protects metadata from any third-parties that don't have access to Threema's servers. However, the E2EE layer fails to protect metadata from anyone with access to Threema's servers. This includes server admins, as well as anyone who manages to compromise the servers.

To demonstrate this issue, I refer to Threema's source code. Specifically BoxedMessage.java, lines 54-61:

Note: I have annotated the source with my own comments

	public byte[] makeBinary() {
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
              /* `bos` is the data to be sent to the server. `bos` is encrypted in the transport layer before sending, but anything written to `bos` is visible to the server */
		try {
			bos.write(fromIdentity.getBytes());
			bos.write(toIdentity.getBytes());
			bos.write(messageId.getMessageId());
			EndianUtils.writeSwappedInteger(bos, (int) (date.getTime() / 1000));

The only line we're really concerned with is line 58: bos.write(fromIdentity.getBytes());

This is where you see Threema sending message senders to the server. This means Threema's servers can see who sent a message, who the message is intended for, and when it was sent.

Simply changing that one line of code would be sufficient to prevent metadata leaks. It would be trivial to encrypt the message sender without breaking the protocol. However, Threema's developers chose not to.

Why would they do this?

I cannot know why Threema's developers chose such a design, but I can venture a couple guesses:

I would hesitate to claim this is intentional, since we cannot truly know why Threema's developers did this. But either way, Threema leaks metadata; making its privacy against attackers with access to Threema's servers comparable to the pseudonymity of Bitcoin. It provides some level of protection by virtue of anonymous identities, but not enough to sufficiently address the issue.

All original non-code/non-software content is committed to the public domain, except where otherwise explicitly stated. Code/software is licensed under the BSD 3-clause license, except where otherwise explicitly stated. Content not originally created by Serpent Security may be subject to separate licensing terms.