DEV Community

Mohammad Taha Azizi Ahad
Mohammad Taha Azizi Ahad

Posted on

Post-quantum messaging in the browser: why I added ML-DSA signatures to my messenger

A few days ago I wrote about building a post-quantum encrypted messenger that runs entirely in the browser. The encryption part got the most attention — and rightly so. But encryption alone was never the whole story. This post is about the part I added next, and why it mattered just as much: identity signatures.

Encryption is not authentication

My protocol, PQ-MPRBA, started with a hybrid key exchange: ML-KEM-768 combined with ECDH P-256, feeding into HKDF-SHA256 and AES-256-GCM. That gives you confidentiality — nobody in the middle can read your messages, not today and not with a future quantum computer.

But confidentiality answers only one question: can anyone read this? It does not answer a harder one: am I really talking to you?

If an attacker can swap in their own public key, they can sit in the middle of a conversation that is perfectly encrypted — just encrypted to the wrong person. Classical signatures like ECDSA would not save you here either, because a sufficiently powerful quantum computer breaks those too. So a post-quantum messenger needs post-quantum signatures, not just a post-quantum key exchange.

What I added: ML-DSA-65 identity signatures

The upgrade signs each identity bundle: the ML-KEM-768 public key is now published together with an ML-DSA-65 signature over it, and the other side verifies that signature before trusting the key.

In practice this changed three things in the app:

  1. A real badge, not a vibe. A contact only earns the PQ badge when both pieces check out: a valid ML-KEM key and a valid ML-DSA signature. Either one missing, no badge.
  2. Forged keys get called out. If a signature does not verify, the UI says so loudly — in Persian, in red — instead of silently accepting the key.
  3. Classical fallback stays honest. Where a contact has no PQ material at all, the app still shows the classical fallback state instead of pretending otherwise.

Three lessons from the upgrade

Signatures are as important as encryption. Everyone talks about key exchange when they talk about post-quantum migration. In a messenger, authentication is where a real attacker actually starts.

Hybrid is pragmatic, not impure. Keeping ECDH alongside ML-KEM during the transition is not a weakness to hide — it is how you ship something that works with both today's infrastructure and tomorrow's threats. The honest thing is to label exactly what is quantum-safe and what is not.

Users need to see trust, not just have it. A badge and a warning in plain language do more for real security than a perfect protocol nobody understands. If users cannot tell a verified contact from a forged one, the cryptography does not matter.

What is still honest to say

This is still an experimental protocol built by one person. It has not been independently audited, and I will not pretend otherwise. The bundle still carries a classical ECDH ephemeral key, so calling the whole thing "fully post-quantum" would be an overstatement — the direction is fully post-quantum, the current state is hybrid and clearly labeled.

That honesty is the point. Post-quantum migration is not a switch you flip; it is a series of steps, each one labeled, each one verified.

The code is open source: https://github.com/indirect-b/chat-app

If you are building something similar, I would love to hear how you handled the authentication side — that is where I learned the most.

Top comments (0)