Encryption, hashing, CSRF protection, and secure operations.
Uses the Web Crypto API for:
- Hybrid RSA-OAEP + AES-256-GCM encryption for PII at rest
- HMAC-SHA256 for webhooks and CSRF tokens
- Argon2-style password hashing
- Constant-time comparison for timing-safe checks
Clear all crypto caches (encryption key, HMAC key, private key, hybrid decrypt LRU) Called on key rotation and during test setup/teardown
Compute HMAC-SHA256 using Web Crypto API, returning raw ArrayBuffer
Compute ticket token index using HMAC for blind lookups Similar to slug_index for events - allows lookup without decrypting
Constant-time string comparison to prevent timing attacks Always iterates over the longer string and XORs the lengths so that different-length inputs don't leak via an early return.
Decrypt a string value encrypted with encrypt() Expects format: enc:1:$base64iv:$base64ciphertext
Decrypt attendee PII using the private key Used in admin views after obtaining private key from session
Decrypt binary data encrypted with encryptBytes().
Decrypt data with a symmetric key
Derive a Key Encryption Key (KEK) from password hash and DB_ENCRYPTION_KEY Uses PBKDF2 with the password hash as input and DB_ENCRYPTION_KEY as salt
Encrypt a string value using AES-256-GCM via Web Crypto API Returns format: enc:1:$base64iv:$base64ciphertext Note: ciphertext includes auth tag appended (Web Crypto API does this automatically)
Encrypt attendee PII using the public key from settings This can be called without authentication (for public ticket forms)
Encrypt binary data with AES-256-GCM. Delegates to encrypt() via base64 encoding for maximum code reuse. Used for encrypting image files before CDN storage.
Encrypt data with a symmetric key (for wrapping private key with DATA_KEY)
Generate a random 256-bit symmetric key for data encryption
Generate an RSA key pair for asymmetric encryption Returns { publicKey, privateKey } as exportable JWK strings
Generate a cryptographically secure random token Uses Web Crypto API getRandomValues
Generate a 5-byte uppercase hex ticket token for public ticket URLs
Get the most recently generated CSRF token (for synchronous JSX rendering)
Derive the private key from session credentials Used to decrypt attendee PII in admin views Results are cached per session token for 10 seconds
Hash a password using PBKDF2 Returns format: pbkdf2:iterations:$base64salt:$base64hash
Hash a session token using SHA-256 Used to store session lookups without exposing the actual token
HMAC-SHA256 hash using DB_ENCRYPTION_KEY Used for blind indexes and hashing limited keyspace values Returns deterministic output for same input (unlike encrypt)
Convert ArrayBuffer to base64 string
Convert ArrayBuffer to hex string
Decrypt data using hybrid encryption Expects format: hyb:1:$base64WrappedKey:$base64iv:$base64ciphertext Results are cached in a bounded LRU (ciphertext -> plaintext)
Encrypt data using hybrid encryption (RSA + AES)
Import a private key from JWK string
Import a public key from JWK string
Check whether a token uses the signed format
Constant-time string comparison to prevent timing attacks
Create a signed CSRF token: s1.{timestamp}.{nonce}.{hmac}
Unwrap a symmetric key Expects format: wk:1:$base64iv:$base64wrapped
Unwrap a key using a session token
Validate encryption key is present and valid Call this on startup to fail fast if key is missing
Verify a password against a hash Uses constant-time comparison to prevent timing attacks
Verify a signed CSRF token's signature and expiry
Wrap a symmetric key with another key using AES-GCM Returns format: wk:1:$base64iv:$base64wrapped
Wrap a key using a session token (derives a wrapping key from the token)
Default message for invalid/expired CSRF form submissions
Usage
import * as mod from "docs/crypto.ts";