Reviewing Signal’s Cryptography, Finale

Contents

  1. Introduction
  2. How Soatok Approaches Cryptography Audits
  3. Mapping Signal and Prioritizing Targets
  4. Message and Media Encryption
  5. Forward-Secure Ratcheting Protocols
  6. Miscellaneous Cryptographic Features
  7. Signal’s New Key Transparency Feature
  8. Summary and Findings (you are here)

Summary and Findings

Over the course of a weekend in February 2025, I set out to review the cryptography used by Signal.

In parts 1-3, I explained the process and mapped out some priority targets.

In part 4, I assessed their usage of symmetric-key authenticated encryption. Although there are some components I would personally design differently, I’m not aware of any attack on the Signal implementations. It should be secure as long as the double ratchet is secure.

In part 5, I briefly examined the Double Ratchet and its components (including the new PQXDH). The only concern that shook out was the abandonment of the pqcrypto-kyber crate in favor of pqcrypto-mlkem. This has been an open issue on libsignal for over a year, so I’m certain that the Signal developers are aware of this.

As of part 5, I concluded that 1:1 messages are forward-secure, and the only concern left was key impersonation. Part 7 would focus on new code in libsignal that implements key transparency, but first, I wanted to assess some of the other cryptography in part 6.

Part 6 is a grab bag of interesting stuff (zero-knowledge proofs, anonymous credentials, algebraic MACs, etc.) that, while apparently secure from an applied cryptography background, would stand to benefit from more peer review from other cryptographers.

In total, no vulnerabilities were found.

This is not my first time reviewing Signal’s source code.

Every time I learn new ways to attack cryptosystems, I always look at Signal or Tor to see if I can break either of them, because they’re difficult targets and you win instant bragging rights if you succeed.

This is the most time I’ve spent writing about a negative result on this blog.

If you read this whole series from start to finish and feel a little disappointed that nothing fell out of my review, I want to make something clear to you in particular:

I didn’t feel that “I looked at Signal and didn’t find any vulnerabilities in it” is exactly a convincing argument, so instead, I wanted to lead you down the journey I took to review Signal; to show you the code snippets I reviewed, and what (if anything) significant I thought about them.

The journey is more important than the destination. I hope this helps more people get comfortable with the basics of reviewing cryptographic software.

If you walk away from it with more confidence in the security of Signal too, that’s cool, but I don’t think most people get their security advice from gay furry bloggers.

Every time I’ve criticized a so-called Signal competitor, someone inevitably moaned about me not aiming the same level of ire towards Signal.

But here’s the thing: Nobody at Signal knew this review was coming. They’re finding out at the same time as everyone else.

And, like my criticism of Session, if I had found any vulnerabilities, I would have fully disclosed them here too.

I don’t think Signal is perfect, by any means.

The lack of group moderation tools makes me pause to recommend it as a replacement for Telegram group chats.

The inability to post a sticker in response to another message (instead of just a standalone sticker) really adds friction to my preferred way of actually using stickers.

But if you need a tool to communicate privately with your friends and family–even if your chats are boring, mundane, and totally legal–Signal is the best damn choice I can recommend.

Maybe I’ll learn more about zero-knowledge proofs and find a vulnerability in their relevant protocols someday.

Or maybe you will, instead?

This Is Not An Audit

This was a timeboxed independent review of Signal’s cryptography implementations.

I did everything substantial over the course of a weekend, and then spent most of the following Monday (President’s Day in the United States) writing this up. Suffice to say, it’s a bit rushed.

A formal audit from a team of cryptography and security experts, over the course of multiple weeks full-time, would be more in-depth than what I was able to muster in a weekend by myself.

If you’d like an even smaller timeboxed review of your project, I started offering Critiques at the end of 2024. These are not meant to replace audits or penetration testing.

Addendum (2025-02-19)

The Hacker News comments about this write-up have exhibited a lot of confusion about what capabilities the Signal Server has, and how that intersects with users’ individual threat models.

Many of these comments come from Matrix/XMPP evangelists and other people that care more about Data Sovereignty than they do about cryptography.

This is what I understand from reading the source code:

In the absolute worst case, a totally malicious Signal Server can perform traffic analysis to correlate the IP address assigned to the messages arriving with the delivery token for a recipient.

An astute reader will notice that this is the same level of traffic correlation that every XMPP or Matrix server operator has.

However, this requires actively malicious, or actively compromised, Signal Servers in order to perform. If an attacker tries to retroactively determine who sent a message, and to which recipient, there are a lot of cryptographic mechanisms built-in that prevent the Signal Server from learning any of this information.

First, you have Sealed Sender (Signal blog on the subject), which completely encrypts the metadata about who sent a message, so that only the recipient can decrypt it.

Sealed Sender cannot totally hide the recipient (else the server wouldn’t know where to route the messages). But what they do instead is route messages to a 96-bit Delivery Token which is derived from a user’s profile key (which is also encrypted).

Crucially, whenever you block a user, your profile key (and thus, delivery token) are rotated.

Additionally, the zero-knowledge proofs ensuring the integrity of encrypted groups was put in place to hide group memberships from the server.

When you combine these observations together, the amount of retroactive analysis the server can even theoretically perform is pretty much nonexistent.

This isn’t to say that Signal offers the same kind of anonymity as the Tor network. Rather, my point is that the privacy consequences of the Signal server are wildly overblown by the same kind of tech news commentators that think “hosted in Switzerland” is a sound argument for a private messaging app’s trustworthiness (rather than its use of cryptography).

It’s telling that their response to any criticism about the amount of trust that XMPP or Matrix servers are given is, “Host it yourself.”

Okay, try telling that to everyday users that don’t even know what a directory is. Meanwhile, real encrypted messaging apps lower the barrier to entry for the same users that are neglected by these “if you’re incapable of self-hosting, you don’t deserve privacy” mindsets.

If you can’t meet people where they are and still provide excellent encryption, you aren’t ready to be a Signal competitor.

(That isn’t to say that federated encrypted messaging apps cannot ever meet the bar set by Signal. But they should focus more on improving their use of cryptography than weak arguments about jurisdiction or data sovereignty.)

Soatok hugging a giant pink heart while making a blep face
Art by AJ