How It Works
- Compose your secret — Enter text (a password, API key, config snippet) or select a file
- Client-side encryption — The browser generates a random passphrase and encrypts the content with OpenPGP symmetric encryption
- Server stores ciphertext — Only the encrypted payload is sent to the server, which stores it in Redis with an expiration timer
- Share the link — The generated URL contains the secret identifier in the path and the decryption key in the URL fragment (
#), which browsers never transmit to the server - One-time reveal — When the recipient clicks “Reveal Secret”, the server returns the ciphertext and atomically deletes it. The browser decrypts using the key from the fragment
The decryption key lives exclusively in the URL fragment. It is never included in HTTP requests, server logs, or analytics. The server only ever stores and returns OpenPGP ciphertext.
Use Cases
- Passwords and credentials — Share login details with a colleague without leaving a trace in Slack or email history
- API keys and tokens — Distribute secrets to developers or CI systems without committing them to a repository
- Sensitive documents — Share contracts, tax forms, or private notes that should not persist anywhere
- Incident response — Relay compromised credentials to security teams over a channel that guarantees single use
Key Features
Zero-Knowledge Encryption
Secrets are encrypted using OpenPGP symmetric encryption entirely in the browser. The server receives and stores only the armored ciphertext. There is no key escrow — if the link is lost, the secret is unrecoverable.One-Time Read
Every secret is deleted from storage the moment it is retrieved. The server uses an atomicGETDEL operation in Redis to ensure the ciphertext cannot be read twice, even under concurrent requests.
Automatic Expiration
Secrets that are never retrieved are automatically purged after their expiration window. The expiration is configurable between 1 minute and 7 days (default: 1 hour). Redis TTLs handle cleanup with no background jobs required.Text and File Support
Both plain-text secrets and encrypted files are supported through separate endpoints. Files follow the same encryption and one-time-read model as text secrets.No Account Required
Secret sharing is fully anonymous. Neither the sender nor the recipient needs to create an account or authenticate.API Endpoints
All endpoints are served under the/api/file-sharing prefix.
Create a Text Secret
OpenPGP-encrypted (armored) secret message. Maximum 1 MB.
Time-to-live in seconds. Minimum 60 (1 minute), maximum 604800 (7 days).
201 Created):
message field in the response is the secret’s UUID identifier, not the encrypted content. Use this identifier to construct the share link.
Fetch a Text Secret
200 OK):
404.
Create a File Secret
message field.
Fetch a File Secret
Security Properties
| Property | Implementation |
|---|---|
| Encryption algorithm | OpenPGP symmetric encryption (AES-256) via the openpgp library |
| Key management | Random passphrase generated client-side, embedded in URL fragment only |
| Zero knowledge | Server stores and returns only armored ciphertext; decryption key never reaches the server |
| Atomic deletion | Redis GETDEL ensures ciphertext is read at most once, even under race conditions |
| Automatic expiry | Redis TTL purges unclaimed secrets after the configured expiration window |
| Rate limiting | 30 creates per 10 minutes and 60 fetches per minute per IP address |
| Payload limit | 1 MB maximum for encrypted payloads, enforced server-side |
| No persistence | Secrets live only in Redis (in-memory); nothing is written to disk or a database |
Share Link Format
The share link follows this structure:{secret_id}— UUID identifying the stored ciphertext, sent to the server#{decryption_key}— OpenPGP passphrase in the URL fragment, never sent to the server