Encryption
Generate keys with base keygen and mint tamper-proof encrypted tokens.
Base ships an encrypted-token service for the classic needs (email-verification links, password-reset tokens, signed state in cookies or URLs), built on AES-GCM encryption with HMAC signing, with key rotation designed in from the start.
Generate a key
Prints a fresh key entry (TOML by default; --format json for JSON):
Replace the <key-id> placeholder with a name of your choosing ("2026-08" works well; you'll thank yourself at rotation time). The command only prints; nothing is written anywhere.
Configure ENCRYPTION_KEYS
Keys live in the ENCRYPTION_KEYS environment variable as an array, because rotation means multiple live keys. In env.toml:
To rotate: generate a new key, prepend it, and keep the old ones listed until tokens minted with them have expired: new tokens use the newest key, old tokens still decrypt.
Mint and verify tokens
The four methods: encrypt/decrypt for opaque strings (cookies, headers), encryptForUrl/decryptFromUrl with URL-safe encoding for links. All four take an optional authenticatedData string that binds a token to its context: pass the account id when encrypting and again when decrypting, and a token lifted from one context won't decrypt in another.
decrypt returns null on any failure; it never throws. Wrong key, tampered payload, garbage input, hostile cookie: all null, by design, so junk input can't crash a request. Every decrypt call needs its null-check, as above.
What this is for: And not
Encrypted tokens carry short-lived, self-contained state across an untrusted hop. They are not session storage (that's the access-control provider and its backing store), not password hashing (one-way hashing is a different tool), and payloads should stay small and expirable: put an expiresAt inside and check it, as the example does.