Security architecture · v1

Encryption that's already quantum-ready.

Qubble Chat is built on cryptographic primitives that don't break when a sufficiently large quantum computer arrives. We use no asymmetric key exchange. No RSA, no ECDH for room keys, no Diffie-Hellman handshakes over the wire. Everything is symmetric, derived locally, and unbreakable by Shor's algorithm.

Threat model — what we defend against

✓ A passive observer on the wire

The Qubble Chat server only sees ciphertext + length. Cleartext never leaves your browser. TLS handles transport; AES-256-GCM handles the room.

✓ A compromised server operator

Room keys are derived from a URL fragment that never crosses the network. The operator can read encrypted blobs only — they cannot decrypt them, and they cannot inject messages without breaking AES-GCM's authentication tag.

✓ A future quantum adversary

Symmetric AES-256-GCM degrades to a 128-bit security level under Grover's algorithm — still well above any feasible attack. We use no asymmetric crypto for key exchange, so Shor's algorithm has nothing to attack.

✓ Forward secrecy compromise

Each message uses a fresh key derived from a one-way ratchet. Compromising the current ratchet state cannot decrypt any past message.

What we don't claim

Cryptographic primitives

Symmetric cipherAES-256-GCM (NIST SP 800-38D)
Key derivationHKDF-SHA-256 (RFC 5869)
Forward secrecySymmetric one-way ratchet
Key exchangeNone (out-of-band via URL fragment)
IV96-bit cryptographically random, fresh per message
Auth tag128-bit AES-GCM authentication tag
Random sourceWeb Crypto crypto.getRandomValues()
RNG auditBrowser-provided CSPRNG — same source Web Authentication uses

What an attack looks like (and why it fails)

Scenario: a state actor records every byte of traffic for 20 years

They get a pile of encrypted blobs. Without the room key — which lives in the URL fragment after a #, never sent to the server — every blob is indistinguishable from random. They cannot brute-force AES-256-GCM with classical hardware (a single-key recovery is ~2256 operations). Under Grover's algorithm on a future quantum computer, that drops to 2128, which is still beyond any feasible attack horizon for the foreseeable future.

Scenario: server operator hands logs to a third party

The logs contain ciphertext + length + timing. No room keys, no plaintext, no participant identity (codenames are user-chosen and not bound to anything). The third party can see that communication happened. They cannot see what was said.

Scenario: someone intercepts the URL link as you share it

They now have the room key — same as if you'd shared a password. This is why every share link is treated as a credential. Use the in-app share flow over an already-trusted channel (Signal, in-person QR scan, etc.). The app's "PUBLIC" link mode tunnels the URL through Cloudflare's edge over TLS — the operator never sees the fragment.

The ratchet, visualized

INITIAL KEY (HKDF from URL fragment) │ ▼ ┌─────────────┐ message #0 ┌────────────┐ │ chain state │ ───────────────▶ │ message 0 │ AES-GCM(key₀, iv₀, plaintext) │ counter:0 │ └────────────┘ └──────┬──────┘ │ │ HKDF derive next state │ iv₀ = random 96 bits ▼ ▼ ┌─────────────┐ message #1 ┌────────────┐ │ chain state │ ───────────────▶ │ message 1 │ AES-GCM(key₁, iv₁, plaintext) │ counter:1 │ └────────────┘ └──────┬──────┘ │ ▼ ... and so on. Compromising key₁₀ leaks NOTHING about keys 0-9. Forward secrecy holds.

Verify it yourself in the app

Every Qubble Chat message has a button that exposes its crypto provenance: the ratchet step number, the IV used, the room key fingerprint, sender, and decrypt timestamp. The persistent Q-E2EE badge in the header pulses every time a message is encrypted or decrypted, so you have a real-time signal that the crypto is alive. No marketing claim — just observable state.

We don't trust security claims that can't be verified. Qubble Chat's security state is exposed in the UI so you don't have to either.

Source & audit invitation