Security architecture
The server stores ciphertext. The link carries the key boundary.
Cinderpass is built so encryption and decryption happen in browsers, while the server only stores opaque encrypted blobs and one-time state. The architecture is less about fancy crypto primitives than about keeping the decryption key physically separate from what the server stores.
System surfaces
Three places, three different trust boundaries.
Client-side encryption
Sender browser
- Generates a fresh random 256-bit AES key with Web Crypto.
- Encrypts plaintext with AES-256-GCM before upload.
- Can optionally protect the key fragment with a passphrase.
Ciphertext storage
Cinderpass server
- Receives ciphertext, IV, note, expiry, and burn state.
- Never receives plaintext or the raw decryption key.
- Marks the secret burned on first successful reveal.
Client-side decryption
Recipient browser
- Reads the `#k` fragment locally from the shared link.
- Requests the encrypted payload using only the secret ID.
- Decrypts in-browser after passphrase verification if required.
Data movement
What moves, and what stays separated.
Upload from sender to server
Sender browser→Cinderpass server
ciphertext + IV + metadata
The plaintext and raw AES key never cross the network.
Shared link between people
Sender→Recipient
/secret/abc123#k=random-key
The secret ID points to the stored ciphertext. The `#k` fragment stays in the browser.
Reveal request from recipient to server
Recipient browser→Cinderpass server
/api/retrieve/:id
Browsers do not send URL fragments in HTTP requests, so the server never sees `#k`.
Key separation
The design works because the two halves stay apart.
Server-visible
- Secret ID
- Ciphertext
- IV
- Expiry, note, burn status
- Optional passphrase verifier data
Browser-local only
- Plaintext before encryption
- Random 256-bit AES key
- `#k` URL fragment
- Recovered plaintext after decryption
Need the full behavior details too?