# timelock.sh — Time-Lock Encryption > Encrypt a file now so it can only be decrypted after a specific UTC minute. timelock.sh publishes X.509 certificates for every minute up to about one month (30 days) ahead; the matching RSA private keys are released to a public API the instant that minute arrives. The entire service is usable with stock `curl` and `openssl` (3.x or newer). No SDK, account, or authentication. Encrypted files are standard CMS AuthEnvelopedData (RFC 5083 / PKCS#7), so anything that can read CMS can decrypt them. ## Time format All timestamps are UTC, truncated to the minute. The API accepts: - `YYYY-MM-DDTHH:MM:00Z` (full RFC 3339) - `YYYY-MM-DDTHH:MMZ` (no seconds — the form embedded in cert CommonNames) ## API Base URL: `https://timelock.sh` - `GET /api/v1/keys/{minute}/cert` — Public X.509 certificate (PEM). Available immediately for any minute up to about one month (30 days) out. - `GET /api/v1/keys/{minute}/key` — RSA private key (PEM). Returns **425 Too Early** with a `Retry-After` header until `{minute}` has passed; once released it is permanent and public. - `GET /api/v1/status` — Service status / health, including the 30-day key horizon. PEM is a plain text format for keys and certificates. In timelock.sh, `/cert` is the public side: it returns the public encryption key packaged inside an X.509 certificate. `/key` is the private side: it returns the matching private decryption key after the unlock minute. ## Encrypt to a future minute ```sh UNLOCK=2026-05-15T00:00:00Z # any UTC minute up to about 30 days out FILE=plaintext.txt # 1. Fetch the public certificate for the target minute. curl -fsS https://timelock.sh/api/v1/keys/${UNLOCK}/cert -o cert.pem # 2. Encrypt. The two -keyopt flags are REQUIRED — without them OpenSSL # defaults to RSA PKCS#1 v1.5, which the in-browser decryptor rejects. openssl cms -encrypt -in ${FILE} \ -recip cert.pem \ -keyopt rsa_padding_mode:oaep -keyopt rsa_oaep_md:sha256 \ -aes-256-gcm \ -outform DER -out ${FILE}.enc ``` The resulting `.enc` is a self-describing CMS blob — it embeds the unlock minute in the recipient's issuer CommonName, so the receiver does not need to be told when it unlocks. ## Decrypt (no prior knowledge of the unlock minute) ```sh INPUT=YOURFILE.enc OUTPUT=decrypted.txt # 1. Self-extract the unlock minute from the file. TIMESTAMP=$(openssl asn1parse -inform DER -in ${INPUT} | grep -oE '[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}Z' | head -1) # 2. Stream the released private key directly into openssl. openssl cms -decrypt -inform DER -in ${INPUT} \ -inkey <(curl -fsS https://timelock.sh/api/v1/keys/${TIMESTAMP}/key) -out ${OUTPUT} ``` If the key has not been released yet, `/key` returns **425 Too Early** with a `Retry-After` header (in seconds) and `openssl` will fail. ## Errors All non-2xx responses use this JSON envelope: ```json { "error": "", "message": "" } ``` Stable error codes: - `invalid_minute` (400) — minute path segment doesn't parse as RFC3339. - `not_found` (404) — no key exists for the requested minute (e.g. > 30 days out, or before the service's earliest minute). - `not_yet_released` (425) — key exists but its private half hasn't been released yet. Response includes `Retry-After`. - `internal` (500) — unexpected server error. ## Constraints and guarantees - Requires OpenSSL 3.x (for AES-256-GCM + RSA-OAEP CMS support). - All times are UTC, minute-granular. Sub-minute precision is not supported. - Public certificates are pre-generated about one month (30 days) ahead. Encrypting to a minute beyond that horizon will 404 on the cert fetch. - Once a minute's private key is released, it is public **forever**. timelock.sh provides "decrypt after time T", not "decrypt only by recipient X". Anyone with the ciphertext after T can decrypt it. - Encryption is end-to-end: plaintext never reaches the server. The browser UI uses WebCrypto; the CLI uses local OpenSSL. ## Pages - [Decrypt UI](https://timelock.sh/decrypt) — drop a `.enc` file in a browser to decrypt client-side. - [CLI docs](https://timelock.sh/docs) — full curl/openssl reference. - [How it works](https://timelock.sh/how-it-works) — architecture and threat model. - [FAQ](https://timelock.sh/how-it-works#faq)