From the wider Nostr network. Not published to a blog here — surfaced from across Nostr. View Leon Acosta’s profile →

post-quantum DMs in Obelisk client

Obelisk has post-quantum direct messages today, and why we should all migrate our clients and relays to support them.

Leon Acosta

August 19, 2026 · 7 min read

Obelisk direct messages are post-quantum encrypted as of this week. Not a demo, not a testnet, not a branch. If you and the person you are writing to have both published post-quantum keys, the message that leaves your client is protected against an adversary who records it today and breaks secp256k1 in fifteen years.

It took no relay changes, no protocol fork, and no new seed phrase for anyone. That is the interesting part, and it is why I think the rest of the ecosystem can follow quickly if we decide to.

What is running#

Post-quantum keys come from the seed phrase you already have. They are derived from the BIP-39 seed as siblings of your secp256k1 key, never from the key itself. That direction is the whole security property: if the post-quantum key could be computed from your Nostr private key, then Shor recovers your private key from your published pubkey, runs the same derivation, and takes the post-quantum key with it. Circular, and worth nothing.

Because it cannot be derived, it gets announced. You publish a kind:10203 event carrying an ML-KEM-1024 encryption key and an ML-DSA-87 signing key, signed by your ordinary Nostr key, with a proof of possession binding all three together. Anyone writing to you reads it off a relay.

The message is an ordinary NIP-17 gift wrap. Inside the seal, the payload combines an ML-KEM shared secret with the normal NIP-44 conversation key through HKDF. Hybrid, never replacement: if ML-KEM turns out to be broken tomorrow you are back to exactly the NIP-44 you have today, which is where every client already is. There is no version of this where you end up worse off.

Cost is about 3 KB per message and roughly a millisecond to encrypt. Clients that have not implemented it are completely unaffected, because the new part sits inside a layer they could not read anyway.

The one gap worth closing#

Right now this is opt-in. You publish keys, the other person publishes keys, and until both happen nothing improves.

I do not think that should be the end state, and I want to be straight about why it is the current one. A Nostr identity is a secp256k1 keypair and nothing else. Your npub is the public half of one specific key on one specific curve. There is no algorithm identifier beside it and no key set, so the protocol cannot express "this identity uses algorithm X". A sender cannot look at an npub and learn anything about what it can receive, which means somebody has to ask, and asking is what makes it opt-in.

The encouraging part is how narrow that gap is. We already solved the same problem one layer up: NIP-44 is versioned, its payloads lead with a version byte precisely so the scheme can change without breaking readers. The idea is already in the protocol and already accepted. It just has not reached the key yet.

That is a much better position than it sounds. This is not a missing concept, it is a missing field.

Why incremental is the right move, not a compromise#

The complete fix is an identity that declares its own key set, with algorithm identifiers and rotation. I want that, and I think it is where we end up.

It is also a change that reaches signatures, and an ML-DSA-87 signature is 4,627 bytes on every event. That is a relay storage and bandwidth question, so relay operators have to be at the table alongside client developers. It needs a NIP, review, several implementations, and a transition that strands nobody. That is a real conversation and it deserves the time it takes.

Meanwhile confidentiality is the half of the problem with an expiry date. Protection against a future break can only be applied before a message is sent, never afterwards, so every day we wait is traffic that no later fix can reach.

The two things run on different clocks. That is the whole argument for doing both rather than choosing.

And the incremental step costs us nothing later, which is the test I would apply to any interim measure. The keys come from the seed people already have. No new identity, no second phrase, nothing extra in a backup. When a proper key-set declaration lands, the same seed derives whatever it needs, and for the person using it migration is a click with their history and identity intact.

If we secure messages today, that is a win. If tomorrow we migrate, it is a click. Those are not in tension, and nothing here has to be undone.

What migrating actually takes#

This is the part I would like people to look at, because it is much smaller than it sounds.

If you build a client. Reading post-quantum messages requires no negotiation and no flag: the envelope leads with a version byte and an algorithm byte, so you inspect the payload and route it. Sending needs the recipient's key from their kind:10203, which is one relay query you can cache for hours. The reference implementation is on npm as @nostr-wot/pq and the wire format is a public draft. Realistically this is an afternoon, not a quarter.

If you run a relay. Nothing changes for messages, since post-quantum payloads are ordinary kind:1059 gift wraps of a slightly unusual size. The one thing to check is the attestation: kind:10203 is about 12 KB, and one relay in our four-relay test set rejects it on size. If your limits would drop it, users on your relay silently cannot be reached post-quantum, and neither they nor the sender find out why.

If you maintain a signer. Two things. Derive the keys as siblings from the seed, never from the private key. And advertise what you accept, so a client can ask instead of guessing: a signer that silently ignores a post-quantum request and returns ordinary ciphertext leads to clients showing protection badges over unprotected messages, which is worse than not supporting it at all.

If you use Nostr. Publish your keys. It is one button in the Nostr WoT extension and takes about five seconds, and it is the only step that has to happen per person rather than per project.

What I am asking for#

The formats are four public drafts in the extension repo under nips/: key derivation, the kind:10203 attestation, the hybrid NIP-44 envelope, and the signer capability marker. None has a NIP number. They are drafts so that someone can tell me the wire format is wrong before a second client ships against it, and I would genuinely rather hear that now.

Three things help more than agreement:

  1. Read the envelope draft and argue with it. Changing it is cheap today and expensive once anyone else has shipped.

  2. If you run a relay, tell me whether 12 KB attestations pass. I have four data points and that is not enough to design around.

  3. If you are working on identity and key sets, I would rather this attestation be replaced by your work than persist beside it. Tell me what shape to build toward and I will build toward it.

The outcome I want to avoid is a Nostr where post-quantum protection is five incompatible bolt-ons, each solved privately. That is the default result if we all move separately, and it is avoidable if the identity layer moves before the workarounds harden.

We can protect messages this month and still design the right thing properly. I would like to do both.

#cryptography#cybersecurity#encryption#nip17#nostr#obelisk#postquantum#pqc#privacy
0

Written by

courage is our own fountain of wisdom 🌱 https://quantakrypto.com

leon@hodl.ar

Comments0

No comments yet. Start the conversation.