Your Signal Safety Number Is Only Useful If You Compare It
Signal's end-to-end encryption has a gap that no amount of cryptography inside the app can close: when you first message someone, you have to take the key you were given on trust. The safety number is the tool that closes that gap, and almost nobody uses it.
This is a short tour of what the number is, what it can and can't catch, and the one habit that makes it worth having.
The problem: who gave you that key?
When you start a conversation, your client asks Signal's server for your contact's public identity key and some prekeys. Then it encrypts to them. The server is a directory, and a directory can lie.
If the server (or someone who has compelled or compromised it) handed you a key it controls, it could sit in the middle, decrypt, read, re-encrypt to the real recipient and pass things along. Both ends would see a perfectly normal encrypted chat. The padlock would be there. Nothing would look wrong.
This is the classic trust-on-first-use arrangement, the same one SSH uses for host keys. It is fine most of the time, and it fails silently in exactly the situation you were worried about.
What the safety number actually is
The safety number is a fingerprint of both parties' identity keys, shown as 60 digits in groups of five, plus a QR code that encodes the same thing. Each side's identity key (together with a stable identifier for that account) is hashed into a short digit string, and the two are combined.
The useful property is that it is the same on both phones. If you and your contact see identical digits, then each of you has the identity key the other one actually holds. A man in the middle would have to hold a different key towards each of you, which produces different numbers on each side.
- Same digits on both devices: no one substituted a key.
- Different digits: someone did, or one of you is looking at the wrong conversation.
What the "safety number changed" warning does and doesn't do
Signal will tell you in the chat when a contact's safety number changes. That is useful, and it is also the part people mistake for protection. The warning only fires when the key differs from the one you saw before.
If the substitution happened before your first message, there is no earlier key to differ from. You never saw the real one, so nothing changes, and no warning appears. The change notice catches swaps after first contact; only comparison catches a swap at first contact.
Why the warning gets ignored anyway
Most changes are boring. Someone reinstalled the app, got a new phone, or re-registered after losing the old handset. Each of those makes a new identity key and a new number.
So you see the warning a few times a year, it is nearly always harmless, and you learn to tap through it. That is the failure mode: the one time it matters looks identical to the dozen times it didn't.
How to compare it properly
The comparison only means something if the channel you use can't be tampered with by the same attacker you are checking for. Reading the digits out over the chat you are verifying proves very little, because a man in the middle could rewrite those messages too.
Better, roughly in order:
- In person: open the contact's safety number screen and scan the QR code on their phone. The app does the comparison for you.
- A voice or video call you trust, where you recognise the person, reading the digits aloud.
- A different channel entirely (a call, a letter, something you already trust), if you can't meet.
Compare the whole thing, not the first couple of groups. A partial match is cheaper for an attacker to fake, since they only need to find a key whose fingerprint agrees on the part you check. Sixty digits is long because it is meant to be compared in full.
Then mark it verified
Once the numbers match, mark the contact as verified in Signal. That records your decision, so a later change is a real event rather than background noise.
From then on, a change warning on that contact means "this person's key changed since you checked". It is still usually a new phone, but now you have a concrete next step: ask them on another channel, and if it was them, compare again.
Quick detour: why a number and not just a key?
Hang on, why not show the raw public key? Because a key is 32 bytes of binary that nobody can compare by eye, and a hash of it, rendered as digits, is something a human can read aloud down a phone line without mistakes. Digits also survive being dictated, which base64 mostly doesn't.
The fingerprint derivation is also deliberately slow to compute (many hash iterations), which makes brute-forcing a lookalike key more expensive. I won't quote the exact iteration count here; the Signal documentation and source are the place to check it.
What it doesn't protect against
- A compromised phone. If someone has your device, the verified key is not the problem.
- Someone else holding your contact's unlocked phone, or an extra linked device you didn't notice.
- Metadata: who talks to whom, and when, is a separate question from whether the content can be read.
Linked devices are worth a glance while you are at it. Check the list of linked devices on your own account occasionally, because an attacker with brief access to your phone can add one and read along without breaking any cryptography.
Is it worth the effort for everyone?
For most conversations, no, and that is a reasonable position. Verifying your pizza order is overkill. Verifying the handful of people where the content is sensitive, or where someone has a reason to target you, takes about a minute each and is a one-off.
The cost is low and the check is the only thing that turns "I trust the server" into "I checked". If you have never opened that screen, do it for the two or three contacts that matter most, next time you are in the same room.