Docs
Cryptbin security architecture
Cryptbin targets developers and security-sensitive sharing: the backend only sees ciphertext and retention metadata, while decryption runs in the browser. The key travels in the URL hash, so it is not sent in normal HTTP requests. Optional language hints improve reading—without exposing plaintext to the server.
Security guarantees at a glance
What we protect
- Plaintext is encrypted before upload.
- The API stores ciphertext, IV, and retention metadata.
- Key fragment stays client-side in the URL hash.
What we do not protect
- Compromised endpoint devices or browsers.
- Users sharing full URLs in unsafe channels.
- Secrets exposed before encryption (clipboard/history).
Operational controls
- Expiration windows for automatic invalidation.
- Burn-after-read for single-read workflows.
- Vault-backed fragment recovery for signed-in users.
Public-key encryption
Cryptbin supports two composer modes: legacy link key and public-key mode. Both encrypt plaintext in your browser before anything is uploaded. The difference is who can decrypt and how the decryption secret is delivered.
| Aspect | Legacy link key | Public-key mode |
|---|---|---|
| Content encryption | AES-GCM with a random 256-bit key per note. | AES-GCM with a random 256-bit session key per note. |
| Who holds the content key | Anyone with the full URL (key in the hash fragment). | Only the recipient’s RSA private key on their device. |
| Share URL | /p/<id>#<key> — fragment never sent to the server in normal navigation. | /p/<id> — no decryption material in the URL. |
| Server stores | Ciphertext, IV, metadata; optional vault-encrypted fragment for recovery. | Ciphertext, IV, RSA-OAEP–wrapped session key, sender signing public JWK, sender fingerprint, ECDSA signature over a canonical payload. |
| Signer identity | Not cryptographically attributed in the payload. | ECDSA P-256 signature over ciphertext, IV, wrapped key, and sender fingerprint; verifier uses the stored signing public key. |
| Cross-device vault recovery | Supported when signed in and vault password is enabled. | Not used for public-key notes (vault encrypts the legacy fragment only). |
Cryptography details (public-key mode)
- Recipient encryption key: RSA-OAEP with SHA-256, 2048-bit modulus, public exponent 65537. The session key bytes are encrypted to the recipient’s public encryption JWK from their published bundle.
- Sender signing key: ECDSA over the P-256 curve; the signed message is a stable JSON serialization of ciphertext, IV, wrapped session key, sender fingerprint, and a fixed format version.
- Identity bundle: Each device generates a local identity (encryption + signing key pairs). Only the public bundle (version, two public JWKs, fingerprint) is meant to be shared or published. Private JWKs stay in localStorage for that browser profile.
- Fingerprint: SHA-256 (hex) of a canonical JSON encoding of the public encryption and signing JWKs plus version. Composers can compare fingerprints out of band to detect directory key rotation.
Key directory
- Signed-in users can publish their public bundle to user_key_directory so others can resolve them by username or by a separate directory email field.
- Directory email is stored on the directory row. On first publish it defaults to your Supabase Auth email if you omit it; you can change or clear it later in Settings. It is not automatically the same as auth email after you edit it.
- Lookup is available only to authenticated clients; results return public bundles and fingerprints, never private keys.
Threat and usability notes
- Public-key mode reduces “URL leak = content key leak,” but anyone who can use the recipient’s unlocked browser or private key material can still decrypt.
- Loss of the device identity (cleared storage, lost backup) means you cannot decrypt notes sent to you unless you have another copy of the private keys.
- The host still sees metadata (timestamps, expiry, burn flag, language hint) and ciphertext shape; it does not see plaintext or, in public-key mode, the session key.
Encrypted forms
Encrypted forms let a creator publish a form definition and receive answers that are encrypted to the creator's public key. Responses are encrypted in the submitter's browser before upload, so the backend stores ciphertext and envelope metadata, not plaintext answers.
What is encrypted vs metadata
- Encrypted payload: the response body (all answers + timestamp) is encrypted client-side before submit.
- Stored envelope data: ciphertext, IV, wrapped AES key, sender signing public JWK, sender fingerprint, and signature for integrity verification.
- Plaintext metadata: form title, form field schema, creation timestamps, and creator-level control flags (for example open/closed state and notification preference).
Submission lifecycle
- Creator publishes form
The creator defines fields (text, long text, checkbox, single/multi-choice, date) and publishes a form with their public identity bundle.
- Submitter fills and encrypts
The submitter loads the form, completes answers, and the browser encrypts the response to the creator's public key and signs the envelope.
- Server stores ciphertext only
The API stores encrypted submission records under the form and does not need access to plaintext answers.
- Creator decrypts in dashboard
The creator opens submissions in the dashboard and decrypts responses locally in the browser with their private keys.
Collection controls
- Forms can be open or closed to new submissions.
- When closed, the submission API rejects new responses and the public form view indicates that the form is no longer accepting submissions.
- Creators can resume collection later, or delete the form (which removes form submissions tied to it).
Notification behavior
- Creators can enable notification emails for new submissions.
- Notification emails contain metadata and a dashboard link for review; decryption still happens in-browser in the dashboard flow.
Form submission identity
Besides the encrypted answer payload, Cryptbin can store a small amount of submission metadata to help form owners triage responses. This metadata is not part of the encrypted answers blob; it is stored alongside the ciphertext record.
Verified identity (signed-in submitters)
- If you are signed in, you may see an optional checkbox to share verified account identity with the form owner.
- When enabled, the service can store your verified account email (and user id) as a trust signal for the form owner. When disabled, that verified identity is not stored.
- This is consent-based: identity is not shared by default.
Provided contact email (optional)
- You can optionally enter a contact email for the form owner. This is user-provided text and may differ from your verified account email.
- It is useful when you want a reply address without enabling verified identity, or when you want a different contact address than your account email.
What stays end-to-end encrypted
- Your form answersremain encrypted to the creator's public key in the browser before upload.
- Identity metadata does not change the encryption model for answers; it only affects optional fields stored next to the submission record for display in the owner dashboard.
Structured secrets (key-value)
Structured secrets are encrypted key-value payloads designed for configuration-style data (for example environment variables, API tokens, or grouped credentials). The values are encrypted client-side before upload, while labels are preserved inside the encrypted payload to keep field context during decryption.
Use case and format
- Best for sharing multiple related secrets as one secure object instead of flattening into free-form text.
- Data is modeled as ordered entries with label and value fields; decryption reconstructs the original pair list for table-style viewing.
- The payload supports many entries and large values, making it suitable for `.env`-style bundles.
Encryption behavior
- Content is encrypted in-browser with the same core model used for snippets/files (ciphertext + IV stored server-side).
- In legacy mode, the decryption key remains in the URL fragment; optional vault backup can protect that fragment for cross-device recovery.
- In public-key mode, data is encrypted to a recipient public key and decrypted only with the recipient's private keys on-device.
Operational notes
- Structured secrets are currently a signed-in workflow in the create surface.
- As with other content types, plaintext never needs to be sent to the API; the host stores encrypted payload and metadata.
- Link handling remains critical: anyone with the full legacy URL can decrypt, and in public-key mode anyone controlling recipient private keys can decrypt.
Vault recovery
Vault recovery helps you rebuild full legacy share links, including the URL hash fragment that carries the decryption key, after you have saved a vault-protected copy with your account. It applies to legacy link-key notes only. Public-key notes use a different model (no fragment key in the URL for the recipient); vault recovery does not apply there.
When you create a legacy note
- Sign in so the paste can be tied to your account and the optional recovery payload can be stored.
- Enable cross-device recovery and enter a vault password in the create form. That password is processed only in your browser; it is not uploaded to Cryptbin.
- The browser derives a key (PBKDF2 with a random salt) and encrypts the fragment with AES-GCM. The API receives only the resulting ciphertext plus salt and IV (and normal paste metadata). The raw fragment and vault password never appear in plaintext on the server.
How a password is “checked” later
Cryptbin does not store your vault password, and we do not store a separate password record for comparison. When you enter a password again, your browser derives a key from the stored salt and attempts to decrypt the vault ciphertext. If decryption succeeds, the password was correct; if it fails (for example wrong password or corrupted data), recovery does not proceed.
Recovering on another device
Use the Dashboard while signed in: enter your vault password in that browser so the client can decrypt the stored fragment and rebuild the full link as /p/<id>#<fragment>. For convenience, the app may keep the password in memory for that session only; it is not written to our database.
Dashboard vault status meanings
- Ready now: this browser already has a usable share URL for the row, so you can open it immediately.
- Unlockable: the row includes vault-encrypted fragment metadata (ciphertext + salt + IV), so entering the correct vault password can recover the full share URL.
- Local-only: no recoverable vault fragment is stored for that row. If this browser does not already have the full URL locally, the link cannot be rebuilt from the server copy alone.
Public-key notes
Decryption relies on the recipient's private keys in the browser. Vault recovery does not substitute for that. It only addresses the legacy fragment backup described above.
Create lifecycle
- Compose
Author content, choose legacy or public-key encryption, optionally set syntax highlighting for viewers (stored as a hint), expiration, and burn-after-read. Resolve a recipient key from the directory or paste a public bundle.
- Encrypt in browser
Legacy: random AES-GCM key and IV, key placed in the URL hash. Public-key: random session key, RSA-OAEP wrap to recipient, ECDSA signature from your local identity.
- Upload ciphertext
Only ciphertext, IV, mode-specific fields, and metadata are sent to the API.
- Return share URL
Legacy URLs append the key material in the fragment. Public-key URLs omit the fragment; the recipient decrypts using keys on their device.
- Burn-after-read
If enabled, the paste row is removed after the first successful read (decrypt), so the link cannot be reused. Combine with short expiry for time-bounded one-time sharing.
API rate limits
The thresholds below are intentionally conservative. While Cryptbin is in beta, tighter caps let us validate performance, observe real-world behavior, and tune abuse protections before we scale to general availability. Expect these numbers to change as the product matures; we will keep this page aligned with the current policy.
Limits are enforced on the server (per IP and, when signed in, per account). They cannot be bypassed from the browser. 429 responses include Retry-After (seconds).
Note creation
- Not signed in: 1 created note per rolling 24 hours per IP address.
- Signed in: 10 created notes per rolling 24 hours per account, and 15 per rolling 24 hours per IP (shared networks may hit the IP cap first).
Reading notes (fetch ciphertext)
- 10 API requests per minute per IP to load or burn a note.
Key directory API
- Publish public keys: 5 requests per minute per IP.
- Update directory profile: 5 requests per minute per IP.
- Lookup recipient keys: 20 requests per minute per IP.
Sign-in email (magic links)
- Magic-link and OAuth flows are handled by Supabase Auth; send limits follow your Supabase project and provider settings, not these API caps.
Email sharing
After you create a note while signed in, the success screen can send the share link to an address via Cryptbin’s email integration. Delivery is optional and rate-limited; it does not change how encryption works.
Requirements
- You must be authenticated; the API checks your session token.
- The operator must configure Brevo (BREVO_API_KEY, BREVO_SENDER_EMAIL, optional sender name and support email). If email is not configured, the API returns a service-unavailable style error.
- Public-key compose flow can optionally email the resolved recipient: if their directory row includes an email, you can opt in to send the link automatically after create. That uses the directory email on the key row, not a live read of Auth at send time.
Rate limits (current API behavior)
- Per IP: 3 sends per 10 minutes.
- Per signed-in user: 2 sends per 10 minutes.
- 429 responses include Retry-After guidance.
What the email contains
- The message includes the full share URL as a button and as plain text. For legacy notes, that URL contains the hash fragment with the decryption key—treat the email as highly sensitive and avoid forwarding.
- For public-key notes, the URL has no fragment key, but the link still identifies the ciphertext the recipient can decrypt with their private key; operational secrecy of the inbox and thread still matters.
- The template states who triggered the send (your Auth email as the “sender” line).
Operational caution
Email is not end-to-end encrypted by Cryptbin. Your provider, infrastructure, and recipient mail paths may log or inspect headers and bodies. Use email sharing only when that risk fits your policy; otherwise copy the link through a channel you trust.
Threat model boundaries
Server compromise scenario: an attacker that only gets database access sees ciphertext and metadata, not plaintext keys.
Client compromise scenario: if an attacker controls the endpoint, plaintext and fragments can be exposed. Endpoint hygiene remains critical.
Link-handling scenario: sharing full URLs grants access; fragment secrecy is only as strong as your transport channel.
Operational notes
- Loss of fragment means loss of decryptability for that link.
- Vault password enables cross-device recovery of supported links.
- Audit usage with retention policy aligned to data sensitivity.
- Prefer short expirations for high-risk data categories.
