Most “secure share” tools still touch your secret.

They encrypt on their servers, require accounts, log metadata, or retain the ability to decrypt later. ChronoLock does none of that.

It encrypts in the browser. The server only ever sees ciphertext. There is no account and no telemetry. When the lifetime ends or the secret is revealed once (if you choose), it is gone.

The full source is public: github.com/Nuem8/ChronoLock (GPL-3.0).

The core rule

Everything sensitive happens in the browser using the Web Crypto API.

A random 32-byte key and 12-byte IV are generated locally. The secret is encrypted with AES-GCM before anything is uploaded. The server receives only the ciphertext plus a few flags (TTL, burn-after-read, whether it is locked to a public key).

You can verify this in two ways:

  1. Open DevTools → Network while creating a secret. Only ciphertext leaves the browser.
  2. Read the source. The encryption path is in the web client; the server never sees key material.

Two ways to lock a secret

1. Key in the link (default)

The raw AES key is placed in the URL fragment (after #). Browsers never send the fragment to the server. Anyone with the complete link can decrypt; a truncated link cannot.

2. Locked to a recipient public key

You paste the recipient’s public key. The secret is encrypted so that only the matching private key can open it. The link itself contains no decryption material. The private key never leaves the recipient’s browser and is never sent to ChronoLock.

If the private key is lost, the secret is unrecoverable. That is intentional.

What the server actually stores

  • Ciphertext
  • Chosen lifetime (5 min / 1 h / 1 day / 7 days)
  • Whether to delete after one successful reveal
  • Whether the secret is locked to a public key

Nothing else. No plaintext, no key, no user identifier, no visit log that identifies the secret.

On reveal the browser downloads the ciphertext and decrypts it locally. If “Delete after one reveal” is enabled, the ciphertext is removed only after a successful decryption with the correct key. A wrong key does nothing. The row is also deleted when its lifetime ends.

The server can run with an in-memory store (dies with the process) or SQLite (keeps unexpired ciphertext across restarts, still without the key).

Limits and deliberate constraints

  • Maximum payload: 8 KB
  • Encryption only works over HTTPS or localhost
  • No accounts, no key recovery, no admin override
  • Longest lifetime is 7 days by default

These are not missing features. They are the design.

Run it yourself

cargo run --release -- --listen 127.0.0.1:8787 --store sqlite --data chronolock.db 

Or memory-only:

cargo run --release -- --listen 127.0.0.1:8787 --store memory 

Put it behind a reverse proxy that terminates TLS. WebCrypto will refuse to encrypt on a public http:// page.

Why this exists

I needed a way to hand someone a temporary credential or recovery code without putting it in email, Slack, or a service that could still read it later. Existing tools either required accounts, kept the ability to decrypt, or added more surface than I wanted.
ChronoLock is the smallest thing that satisfies the requirement:

I invite users to test and give me feedback on how to improve it. Thanks.