▶ Breaking
Meta is ending end-to-end encryption on Instagram DMs — May 8 2026. Here's what to use instead → // Discord leaked 70,000 government IDs. Why we built this → // OpenDescent v0.5.4 released — hubs, live streaming, signed file sharing. Download → // Normal life deserves privacy. // Meta is ending end-to-end encryption on Instagram DMs — May 8 2026. Here's what to use instead → // Discord leaked 70,000 government IDs. Why we built this → // OpenDescent v0.5.4 released — hubs, live streaming, signed file sharing. Download → // Normal life deserves privacy. //
Security  /  Technical deep-dive v0.5.4 · 2026-04-24

Security, explained without the hand-waving.

How OpenDescent protects your messages, what cryptographic primitives we use, what the threat model actually covers — and, crucially, what it doesn't. If you're a developer, a journalist doing due diligence, or just a careful person, this is the page that shows you our work.

On this page 01Threat model 02Primitives 03Message lifecycle 04Architecture 05Known limits 06Audit status
Short version

Threat model — what we protect, what we don't.

§ 01  /  Scope
Protected

What OpenDescent does protect against.

  • Network eavesdropping Anyone on the path between you and your peer sees only ciphertext. Both your libp2p transport (Noise) and your messages (AES-256-GCM) are encrypted.
  • Server compromise We have no servers, so there's no server-side database to breach. Nothing central stores your messages, contact list, or metadata.
  • Compelled disclosure by a service provider No entity can be subpoenaed for your data because no entity has your data. Courts can't order the production of information that was never collected.
  • Forward secrecy Each message uses a fresh ephemeral X25519 key. Compromise of your long-term key doesn't retroactively decrypt past messages.
  • Tampering in transit AES-GCM authenticates ciphertext; Ed25519 signs a hash of the message. Any modification on the way is rejected at the recipient.
  • Impersonation attempts Every message is signed by the sender's long-term Ed25519 key. TOFU pinning and trust-web vouching surface key swaps to the recipient.
  • Identity theft Your identity isn't tied to a phone number, email, or account. There's no credential to steal in a data breach elsewhere.
Not protected

What OpenDescent does not solve.

  • Compromised endpoint If malware runs on your device, it can read your plaintext before encryption, just like any other E2E app. End-to-end encryption protects the path, not the endpoint.
  • Compromised recipient device We can't prevent the person you're talking to from screenshotting a conversation, being keylogged, or having a malicious extension.
  • Traffic analysis at the IP layer A sufficiently-resourced adversary watching raw traffic could infer that you're using OpenDescent and who you're connected to, even if they can't read message content. Use Tor or a trusted VPN if that's your threat model.
  • Coercion and rubber-hose cryptanalysis If you're compelled to unlock your device or disclose your mnemonic, no cryptography in the world fixes that. OpenDescent doesn't include plausible-deniability features (yet).
  • Peer-level metadata A malicious peer you're connected to can record that you connected to them, and when. This is limited to direct peers; it's not a global view.
  • Quantum-capable adversaries Current cryptography is not post-quantum. A future sufficiently-large quantum computer could break X25519 and Ed25519. Post-quantum primitives are on the long-term roadmap.
  • Mistakes you make Sharing your mnemonic, sending screenshots, trusting a wrong key because you skipped TOFU verification — these are outside the reach of any protocol.

Cryptographic primitives — what's doing the work.

§ 02  /  Ingredients
Ed25519
Identity · Signatures
Edwards-curve digital signatures. Your long-term identity is an Ed25519 keypair. Every message and file manifest is signed so the recipient can verify who sent it and that it wasn't tampered with.
Security128-bit Key size32 bytes Signature64 bytes SpecRFC 8032
X25519
Key agreement
Elliptic-curve Diffie-Hellman. For each message, a fresh ephemeral X25519 keypair is generated on the sender's device. The shared secret is negotiated with the recipient's public key, giving forward secrecy.
Security128-bit Key size32 bytes Ephemeralper message SpecRFC 7748
HKDF-SHA256
Key derivation
HMAC-based key derivation function. Turns the X25519 shared secret into the symmetric key used for the message, with a per-message salt and context info so the same shared secret never reuses a key.
HashSHA-256 Output32 bytes Context"opendescent-msg-v1" SpecRFC 5869
AES-256-GCM
Authenticated encryption
Authenticated encryption with associated data. Protects both confidentiality and integrity — a tampered ciphertext fails authentication and is rejected. Nonce is random per message.
Key256-bit Nonce96-bit random Tag128-bit SpecNIST SP 800-38D
BIP39
Mnemonic backup
12-word mnemonic recovery phrase from a 2,048-word curated wordlist. 128 bits of entropy plus a checksum. Your mnemonic deterministically derives your Ed25519 identity key.
Entropy128-bit Words12 Wordlist2,048 entries SpecBIP-0039
Noise · libp2p
Transport encryption
Every libp2p connection uses the Noise Protocol Framework to establish an encrypted channel between peers. Your E2E messages travel inside already-encrypted tunnels — defence in depth.
PatternXX CipherChaCha20-Poly1305 DHX25519 SpecNoise Protocol
Verifiable

All of these are standard, peer-reviewed, widely-deployed primitives. They are the same primitives used by TLS 1.3, SSH, WhatsApp (Signal Protocol), Age, Wireguard, and the browser you're reading this page in. The innovation in OpenDescent isn't in the primitives — it's in the architecture that removes the server entirely. The primitives themselves are chosen specifically because they aren't novel: novel crypto is dangerous crypto.

Message lifecycle — one message, from your keyboard to theirs.

§ 03  /  End-to-end

What actually happens

When you send "I love you", your device runs through these steps before the message leaves the machine. There's no point at which plaintext is available to anyone other than you and the recipient.

The amber steps are what happens on your device before the message is sent. The teal steps are what happens on the recipient's device after it arrives. The peers in between see ciphertext only.

Pseudocode · per-message flow
// sender side const ephemeral = X25519.keygen() const shared = X25519.dh(ephemeral.priv, recipient.pub) const key = HKDF(shared, salt, "opendescent-msg-v1", 32) const nonce = random(12) const ct = AES-256-GCM(key, nonce, plaintext, aad) const sig = Ed25519.sign(identity.priv, hash(ct)) send({ ct, sig, ephemeral.pub, nonce, salt })
01
You type the message
Plaintext lives in your device's RAM. Not written to disk, not logged, not sent anywhere yet.
RAM · cleartext
02
Generate ephemeral X25519 keypair
A throwaway keypair created for this message only. When the message is sent, the private half is discarded — that's where forward secrecy comes from.
X25519.keygen() · discard after send
03
ECDH with recipient's long-term key
Combine your ephemeral private key with the recipient's long-term X25519 public key to derive a shared secret. The recipient will re-derive the same secret using their private key and your ephemeral public key.
X25519.dh(ephemeral.priv, recipient.pub)
04
Derive symmetric key via HKDF
Run the shared secret through HKDF-SHA256 with a random salt and a context string. This produces the 256-bit key that actually encrypts the message.
HKDF(shared, salt, "opendescent-msg-v1", 32)
05
Encrypt with AES-256-GCM
Random 96-bit nonce. Plaintext becomes ciphertext plus a 128-bit authentication tag. Any tampering will fail verification at the recipient.
AES-256-GCM(key, nonce, plaintext, aad)
06
Sign a hash of the ciphertext
Ed25519 signature over SHA-256 of the ciphertext, using your long-term identity key. Proves this message came from you.
Ed25519.sign(identity.priv, hash(ct))
07
Send through libp2p Noise channel
The envelope (ciphertext, signature, ephemeral public key, nonce, salt) is wrapped in a Noise-encrypted libp2p stream to the next peer. The transport is encrypted; the payload is encrypted; the peers between you see nothing useful.
libp2p · Noise XX · ChaCha20-Poly1305
08
Arrives at recipient device
The message may have hopped through several peers in the mesh, possibly been held in store-and-forward if the recipient was offline. Every hop saw ciphertext.
mesh · peer routing · E2E preserved
09
Verify Ed25519 signature
If the signature doesn't verify against your known public key, the message is rejected. No signature check = no decryption attempt.
Ed25519.verify(sender.pub, hash(ct), sig)
10
Re-derive shared secret
Recipient's X25519 private key + your ephemeral public key → the same shared secret you derived. That's the magic of Diffie-Hellman.
X25519.dh(recipient.priv, ephemeral.pub)
11
HKDF → AES-GCM decryption
Same HKDF derivation → same symmetric key. AES-GCM decryption both decrypts and authenticates; a bad tag means rejected message.
AES-256-GCM.decrypt() → plaintext
12
Plaintext revealed
"I love you" is shown on the recipient's screen. No server saw the plaintext. No company has a copy. The ephemeral key used to encrypt it was discarded after step 02 — nobody can decrypt this message a second time, even with the recipient's long-term key.
✓ delivered · forward-secure

Architecture — why there's nothing to breach.

§ 04  /  P2P vs central

Most messengers — including Signal, the good one — solve privacy with encryption on a central server. The server can't read messages, but it still knows who's talking to whom, when, from where. A compromise of that server, a subpoena, or a policy change can reshape what users can expect.

OpenDescent removes the server entirely. Your messages travel peer-to-peer through libp2p. There is no OpenDescent-operated machine between your device and your recipient's device. There's no DB to leak, no admin account to phish, no IP address log in a data centre.

SERVER
Every message through one place · one breach = all exposed
No centre · nothing to breach · nothing to subpoena
Why this matters

Encryption plus centralisation means you trust a company to keep running its servers honestly. Encryption plus peer-to-peer removes the company from the equation. The guarantees become architectural — they can't be rolled back by a privacy-policy update, because there's no policy surface to update.

Known limitations. The honest list.

§ 05  /  We don't claim what we can't do

Credibility on a security page comes from admitting what the system doesn't do. Here's ours.

Endpoint security is your problem

End-to-end encryption protects the path, not the endpoint. If your device is compromised — malware, a malicious browser extension, a shoulder-surfer — the attacker sees plaintext before it's encrypted. The same applies to the recipient's device. This is true of every E2E messenger, including Signal, WhatsApp, and iMessage. It's a fundamental limit of the model, not a specific OpenDescent weakness.

Traffic analysis can leak information

A state-level adversary watching raw internet traffic can see that your device is running OpenDescent (libp2p has distinctive traffic patterns) and identify which other peers you connect to. We don't hide that you're communicating, only what you're communicating. If hiding the existence of communication is part of your threat model, route OpenDescent over Tor or a trusted VPN.

No plausible deniability

Unlike some protocols (OTR, for historical reasons), OpenDescent signs messages with your long-term Ed25519 key. This is good for integrity and spam resistance, but it means messages are cryptographically attributable — you signed them, and the signature is verifiable forever. If you need deniability for your threat model, consider combining OpenDescent with other tools.

Peer metadata, not zero metadata

A peer you directly connect to can record that you connected, your IP at the time, and packet sizes. This is local metadata, not global — nobody has the whole network graph. But it's not literally zero. If this matters for your threat model, onion-routed Dead Drops are designed for exactly this case.

Not post-quantum yet

X25519 and Ed25519 are safe against classical adversaries. A future large-scale quantum computer could theoretically break them. When post-quantum primitives become standardised and practical (CRYSTALS-Kyber, CRYSTALS-Dilithium, etc.), we plan to adopt them alongside the current stack. For now, "record now, decrypt later" is a real risk against nation-state-class threat models.

No formal audit yet

See the next section.

Audit status & verifiability.

§ 06  /  Trust but verify

No formal third-party audit yet.

OpenDescent is open source under the MIT license and uses standard, peer-reviewed cryptographic primitives. The code is available for anyone to read on GitHub. But we have not yet commissioned a professional cryptographic audit — the kind that firms like Trail of Bits, NCC Group, or Cure53 perform on Signal, SimpleX, and Proton.

A proper audit costs in the tens of thousands of GBP. It's on the roadmap and is one of the specific things the Founder's Edition subscription helps fund. We will not claim "audited" until we are.

Source available
✓ Yes · MIT
Self-buildable
✓ Yes · npm install && npm run build
Reproducible builds
△ In progress
Third-party audit
△ Not yet · on roadmap

What you can verify today

Every cryptographic claim on this page is verifiable by reading src/crypto/ in the repository. The specific files:

If you find a vulnerability or a cryptographic weakness, please disclose responsibly via GitHub Security Advisories. We take reports seriously and respond quickly.

Security questions, straight answers.

§ 07  /  FAQ
Does OpenDescent use the Signal Protocol?01
No. We use standard primitives (X25519, HKDF-SHA256, AES-256-GCM, Ed25519) assembled directly rather than adopting the Signal Protocol's Double Ratchet. The security properties (forward secrecy, integrity, authentication) are comparable for our threat model. The Signal Protocol is excellent and we considered it; we opted for a simpler per-message ephemeral design that fits peer-to-peer delivery better.
How is forward secrecy achieved without the Double Ratchet?02
Every message uses a fresh ephemeral X25519 keypair generated on the sender's device. After the message is sent, the ephemeral private key is discarded. If your long-term key is compromised later, past messages can't be decrypted — their ephemeral private keys are gone.
What happens if someone steals my 12-word mnemonic?03
They can reconstruct your identity and read messages you receive going forward. Past messages remain safe due to forward secrecy. Treat the mnemonic like the master password it is — save it in a password manager, or write it on paper in a safe place. Do not send it in any message, anywhere.
Is the server closed-source like WhatsApp's?04
There is no server. The entire app is open source, MIT licensed, on GitHub. You can read every line, build it yourself, run it locally, and modify it. There's no "closed-source server-side" — because there's no server.
What's the role of libp2p Noise if messages are already E2E encrypted?05
Defence in depth. The libp2p transport encrypts the connection between peers (Noise XX with ChaCha20-Poly1305). Your messages inside that connection are E2E encrypted with AES-256-GCM. A network-level attacker sees Noise(libp2p(AES(plaintext))) — two independent layers of encryption.
Can OpenDescent protect against a state actor?06
For message content, yes — the cryptography is modern and well-understood. For traffic analysis and endpoint targeting, depends on the specifics. A state actor targeting you specifically can likely compromise your endpoint (zero-days, physical access), which bypasses any messenger's E2E. Against passive mass surveillance of communication content, yes. Against a targeted TAO-level adversary, nothing short of air-gapping + Tails + a cold war is sufficient, and even that has limits.
How do you prevent spam without a central registration server?07
Three mechanisms. (1) You only receive messages from peers you've added or who've joined a hub via an invite. (2) Per-identity reputation flows through the trust web — an abuser's new identity has no vouches. (3) For Dead Drops specifically, proof-of-work is required per post. No anti-spam measure is perfect, and this is an area where decentralisation is genuinely harder than centralisation.
How do I report a vulnerability?08
Please use GitHub Security Advisories for responsible disclosure. We aim to respond within 48 hours on weekdays, coordinate on a disclosure timeline, and credit reporters unless they prefer otherwise.
Read the source

The whole codebase is public. Verify everything on this page.

Open source under MIT. Standard, peer-reviewed primitives. No proprietary crypto. No "trust us" — just "read us."