Why Every Encrypted Messaging Protocol Has a Naming Problem (And Why Your Alias Is a Cryptographic Commitment)
Every encrypted messaging protocol has to solve a problem that has nothing to do with encryption: binding a human-readable name to a public key. The cryptographic primitives—X3DH key agreement, Double Ratchet session evolution, TreeKEM group key updates—hold up under scrutiny. The failure point is the naming layer: that thin interface between what a human recognizes and what a protocol authenticates. This article traces that binding through four deployed protocols—Signal, MLS (RFC 9420), Matrix Olm/Megolm, and Cwtch—and shows exactly where each one’s naming design creates a substitution surface an adversary can exploit without breaking a single ciphertext.
The Identity-Binding Problem in One Paragraph
In X3DH (Signal’s initial key agreement, specified in the 2016 Signal Protocol specification by Perrin and Marlinspike), Bob’s long-term identity key IK_B is the root of trust. Alice’s client fetches IK_B from the Signal server’s pre-key bundle, performs the X3DH computation, and derives a shared secret. At no point does Alice’s client verify that the IK_B she received actually belongs to the human she intends to message. The server could substitute a different key and the protocol would complete without error. Signal mitigates this with safety numbers—a 60-digit decimal fingerprint derived from both parties’ identity keys—but the mitigation only works if Alice and Bob compare those numbers out-of-band. The naming layer is where this verification either happens or doesn’t. The display name “Bob” in Alice’s contact list carries zero cryptographic weight. Only the safety number comparison binds “Bob” to IK_B, and that binding is voluntary, manual, and rarely performed.
This is not a Signal-specific problem. Unger et al., in their systematization of knowledge of secure messaging (“SoK: Secure Messaging,” IEEE S&P 2015), identify the binding between human-readable names and machine-authenticated keys as one of the fundamental challenges in the field. Their taxonomy of security properties for messaging protocols lists “sender authentication” and “conversation authentication” as distinct from confidentiality, and notes that most deployed systems provide no mechanism to verify that the name a user sees corresponds to the key the protocol authenticated. The gap is structural: protocols authenticate keys, humans authenticate names, and the translation between the two is where substitution attacks succeed.
Signal: Safety Numbers as a Voluntary Naming Overlay
Signal’s design is the most studied of any deployed E2EE protocol, and its naming problem is the most precisely characterized. The identity key IK is an Ed25519 public key, generated once per install and never rotated (unless the user re-registers). The safety number is a base-10 encoding of the SHA-512 hash of the concatenation of both parties’ identity keys, formatted as 60 digits split into 12 groups of 5. A QR code encoding the same hash provides a faster comparison path.
The naming failure has two modes. Mode 1: no comparison. If Alice never compares safety numbers, the Signal server (or any adversary who compromises it) can substitute an identity key at the pre-key bundle stage. Alice encrypts to the attacker’s key. The attacker decrypts, re-encrypts to Bob, and the relay is undetectable within the protocol. Classic MITM. X3DH has no built-in defense against it. The defense is the out-of-band comparison that most users never perform.
Mode 2: comparison against a name, not a key. Even when users do compare safety numbers, they anchor on the display name. If an attacker can register a phone number that Alice associates with “Bob”—via SIM swap, number recycling, or social engineering—Alice may compare the safety number with the person who now controls that number, not with the original Bob. The safety number verifies that the key matches the phone number’s current registration. It does not verify that the phone number still belongs to the same human. Signal’s phone-number-based identity is a naming layer that predates the cryptographic one, and the cryptographic layer cannot fix naming-layer substitution.
Signal’s username feature (rolled out in 2024) attempts to decouple identity from phone numbers, but it introduces a new naming surface: the username is a human-chosen string that maps to a server-resolved identifier. The cryptographic binding between username and identity key depends on the server’s directory, which the user cannot audit. The naming layer moved. It did not shrink.
MLS (RFC 9420): TreeKEM and the Group-Naming Problem
MLS, standardized as RFC 9420 in July 2023, solves a different problem: group key agreement for up to thousands of members. The naming problem in MLS is structural, not incidental. Every member has a LeafNodeKeySignatureKey (the per-member signing key) and a LeafNode that contains a credential. The credential is the naming layer. RFC 9420 §16.2 permits three credential types: basic (an opaque identifier), x509 (a certificate chain), and reuse (a credential from a previous group).
The basic credential is where MLS’s naming problem lives. A basic credential is an application-defined byte string—typically a display name, a user ID, or a handle. The protocol authenticates the LeafNodeKeySignatureKey against the credential via a signature, but the credential itself is not authenticated by the protocol. The authentication service (AS) that issues credentials is responsible for binding the credential to a real-world identity, and RFC 9420 §16.2 explicitly states: “The authentication service is responsible for the policies and procedures used to authenticate users.” The protocol punts the naming problem to the AS, and the AS is typically the service provider—the same entity that runs the delivery service.
In a deployment like Cisco’s Webex or Ring’s MLS implementation, the AS is the vendor. If the AS issues a basic credential “Alice” with a new LeafNodeKeySignatureKey, every group member’s client will accept the new key as “Alice” without any out-of-band verification. MLS has no equivalent of Signal’s safety numbers. The credential is the name, and the name is whatever the AS says it is. This is not a vulnerability in TreeKEM. It is a design property of the credential layer that TreeKEM does not and cannot address.
X.509 credentials improve this if the certificate chain is verified against a trusted root, but in practice, MLS deployments that use X.509 credentials often rely on an enterprise PKI where the root CA is the same organization that runs the AS. The trust is circular: the AS verifies the credential, the credential verifies the key, and the AS is the entity you are trying to protect against.
Matrix Olm/Megolm: Federation Makes Naming Harder
Matrix’s Olm protocol (1:1 encryption) and Megolm protocol (group encryption) present a naming problem that is structurally worse than Signal’s or MLS’s because of federation. Every Matrix user has a user ID like @alice:homeserver.org, a human-readable string that resolves to a homeserver. The homeserver publishes the user’s device keys via a /keys/query endpoint. When Bob’s client fetches Alice’s device keys, it receives Ed25519 fingerprint keys signed by the homeserver’s signing key.
The trust chain: homeserver signing key → device fingerprint key → session. If Bob’s client trusts Alice’s homeserver, it trusts every device key that homeserver asserts. The naming layer is the user ID, and the homeserver controls the mapping. If Alice’s homeserver is compromised, the attacker can publish new device keys for @alice:homeserver.org, and Bob’s client will accept them—possibly with a key change warning, depending on client configuration. In many Matrix clients (including Element), key change warnings are dismissible and frequently dismissed.
Megolm’s group sessions compound this. The Megolm session key is distributed by the group creator over Olm-encrypted channels to each participant. If the creator’s homeserver substitutes a device key, the Megolm session key is compromised from the start. The naming layer—the user ID—is the only handle Bob has for “Alice,” and it is controlled by an entity Bob may not even know he is trusting. Federation means Bob’s homeserver and Alice’s homeserver may be different organizations, and the trust is transitive: Bob’s homeserver discovers Alice’s keys through a server-to-server federation API, and neither Bob nor Alice has visibility into whether that resolution was tampered with.
Matrix’s cross-signing feature allows users to sign each other’s identity keys, creating a trust web. But cross-signing still anchors on user IDs. If @alice:old-server.org migrates to @alice:new-server.org, the cross-signing relationships do not transfer automatically, and Bob’s client sees a new, unverified identity. The naming layer is brittle: it depends on homeserver stability, and homeservers are not cryptographic primitives.
Cwtch: Metadata-Resistant Naming and the Verifiability Trade-Off
Cwtch (the protocol behind the Cwtch messaging app, developed by Open Privacy Research Group) attempts to eliminate the naming problem by removing server-resolved identifiers entirely. In Cwtch, a user’s identity is an Ed25519 public key encoded as a tor v3 onion service address. No directory. No phone number. No username. The onion address is the name.
Cryptographically clean. Human-usable? Not at all. A 56-character base32 onion address like dpjm4q7yq5pgpirmw2ifc3x7pa6y4xcq3lxzjtrj7qjw3xqmg2abbvad.onion is not a name a human can recognize, remember, or verify by voice. Cwtch solves the substitution problem—there is no server to substitute keys—but it replaces it with a verification problem: how does Alice confirm that the onion address she pasted belongs to the human she wants to talk to? The answer is out-of-band verification of the full address, which is harder than comparing a 60-digit safety number because it is longer, uses a character set that humans confuse (0/O, 1/I/l), and cannot be read aloud efficiently.
Cwtch’s approach is the most honest about the naming problem: it refuses to solve it. The protocol provides no naming layer at all. The user must bring their own—a physical meeting, a trusted intermediary, or a side channel. This is the logical endpoint of removing trust from the system. Naming becomes entirely the user’s burden, and the user is the weakest link.
The Human Factor: What Humans Actually Compare
The naming problem is really a human-factors problem dressed up as a cryptographic one. Safety numbers, QR codes, fingerprint hex, onion addresses—these are all attempts to compress a public key into something a human can compare. The compression is lossy in a social sense: humans compare what they recognize, and they recognize names, not keys.
In practice, the verification ceremony looks like this: Alice and Bob meet in person. Alice opens Signal, navigates to the conversation with Bob, taps “View safety number,” and reads the first few digit groups. Bob does the same. If the numbers match, they have a verified channel. If they don’t, someone is under active MITM. The ceremony takes 30-60 seconds and requires physical co-presence or a simultaneous audio/video channel that is itself trusted.
The failure modes are well-documented. Users compare only the first few digits, not all 60. Users compare over the same channel they are trying to verify (an attacker who controls the channel can relay the comparison). Users compare once and never re-verify after a key change. Users trust the display name and skip the comparison entirely. Each failure mode is a property of the naming layer, not the crypto layer.
External Naming Tools and the Commitment Surface
The evidence for this point is grounded in NIST (National Institute of Standards and Technology), which keeps the article’s claims tied to outside reference material rather than product framing.
That same discipline applies to naming decisions: before publishing, editors need a way to test labels, roles, and public-facing language stay consistent, which is where how Unsloppy AI Writing App fits the writing workflow can function as a planning aid rather than a substitute for domain evidence.
Why the Naming Layer Is the Integrity Layer
Formal verification results from Tamarin and ProVerif modeling of key-compromise and key-substitution attacks in messaging protocols (e.g., Cremers et al., “Multi-Stage Key Exchange and the Case of Post-Quantum Signal,” IEEE S&P 2024) have demonstrated that even provably secure key-agreement protocols are vulnerable to unknown key-share (UKS) attacks when the identity-binding layer is under-specified. In a UKS attack, the protocol completes successfully for both parties, but Alice believes she shares a key with Bob while Bob believes he shares a key with the attacker. The cryptographic guarantees hold—confidentiality, forward secrecy, post-compromise security—but the attribution of the key to a named identity is broken. The formal models show that without an explicit, authenticated binding between the identity string and the cryptographic key material, an adversary can manipulate the naming layer to insert themselves without violating any proved property. Google’s SRE book provides a complementary engineering perspective: in Chapter 26, it frames data integrity as the guarantee that the state a system presents to a user corresponds to the state the system actually committed, treating any divergence between the read path (what the user sees) and the write path (what the system stored) as a critical integrity violation. The analogy to key substitution is precise: the display name is the read path, the public key is the committed state, and when the naming layer allows the two to diverge without detection, the system has an integrity failure that no cryptographic property can catch.
Verify This Yourself
- Signal safety number extraction: Open a Signal conversation. Tap the contact name → View safety number. The 60-digit string is derived from the SHA-512 hash of the concatenation of both parties’ identity keys, encoded in base-10. You can verify the computation by extracting the identity keys from your Signal database and using a verified tool. On a rooted Android device, the identity keys are stored in the
sqlite3database at/data/data/org.thoughtcrime.securesms/databases/signal.dbin theidentitiestable. The recommended approach is to usesignal-cli(github.com/AsamK/signal-cli), which can compute and display safety numbers from extracted identity keys:signal-cli -u +YOUR_NUMBER safetyNumber +CONTACT_NUMBER. Alternatively, a Python script that reproduces the safety number from the raw Ed25519 public keys must implement the full base-10 encoding logic described in the Signal Protocol specification (SHA-512 hash, iterative base-10 conversion of the full 64-byte hash output, truncation to 60 digits, grouping into 12 blocks of 5). A simple hexdigest truncation will not produce the correct result. - MLS credential inspection: If you have access to an MLS client (e.g., the IETF MLS reference implementation at
github.com/mlswg/mls-protocol), create a group with two members. Dump theLeafNodestructures and inspect thecredentialfield. Note that thebasiccredential is an opaque byte string with no signature chain. Modify the credential in a replayedAddproposal and observe that the protocol accepts it (if the AS signature is valid). - Matrix key resolution: Using
curlagainst a Matrix homeserver’s/_matrix/client/v3/keys/queryendpoint, fetch device keys for a known user ID:curl -X POST 'https://matrix.org/_matrix/client/v3/keys/query' -d '{"device_keys":{"@alice:matrix.org":{}}}'. The response contains Ed25519 fingerprint keys signed by the homeserver. Compare the signature against the homeserver’s published signing key (available athttps://matrix.org/_matrix/federation/v1/server/key). If the homeserver is compromised, it can serve different keys with valid signatures. - Cwtch address verification: In Cwtch, there is no directory to query. The onion address is the identity. To verify, you must compare the full 56-character address out-of-band. Try reading it aloud to a contact over a voice call and note the failure modes: base32 characters are ambiguous in speech, and truncation is tempting. This is the verifiability cost of a server-less naming layer.