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
  • PBKDF2-SHA256 password hashing
  • Constant-time comparison for timing-safe checks

Functions

f
aesGcmDecryptBytes

AES-GCM decrypt with raw key bytes. The mirror of aesGcmEncryptBytes; note it measures the ciphertext, which carries the tag the plaintext does not.

f
aesGcmDecryptRaw

AES-GCM decrypt raw data with an imported key

f
aesGcmEncryptBytes

AES-GCM encrypt with raw key bytes, using whichever implementation is faster for this payload.

f
aesGcmEncryptRaw

AES-GCM encrypt raw data with an imported key, returning IV and ciphertext

f
aesGcmEncryptText

AES-GCM encrypt a text string with an imported key

f
computeHmacSha256

Compute HMAC-SHA256 using Web Crypto API, returning raw ArrayBuffer

f
concatBytes

Concatenate byte arrays into one array.

f
constantTimeCodesEqual

Constant-time compare of two code sequences, given their lengths and a per-index code reader for each. Walks the longer sequence and folds every difference into one flag with XOR, so no early return leaks a length or the position of the first mismatch. Callers supply the code source (UTF-8 bytes, UTF-16 char codes, …), keeping this the single constant-time comparison loop.

f
constantTimeEqual

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.

f
constantTimeEqualBytes

Constant-time comparison for Uint8Arrays. Arrays of different lengths are never equal — the length difference seeds the mismatch flags, so no branch on it can leak timing.

f
csrfInvalidFormMessage

Default message for invalid/expired CSRF form submissions (request-scoped).

f
decodeKeyBytes
No documentation available
f
decrypt

Decrypt a string value encrypted with encrypt() Expects format: enc:1:$base64iv:$base64ciphertext

f
decryptBytes

Decrypt binary data encrypted with encryptBytes(). Expects ENCB binary format: magic + version + IV + ciphertext.

f
decryptWithKey

Decrypt data with a symmetric key

f
decryptWithOwnerKey

Decrypt a value encrypted with encryptWithOwnerKey, using the owner's private key (obtained from the session in admin views).

f
deriveKEK

Legacy (v1) KEK derived from the stored password hash. Retained only to unwrap and migrate existing wrapped_data_keys — new wraps use deriveKEKFromPassword. Salt prefix is empty so this stays byte-compatible with keys wrapped before the v2 split.

f
deriveKEKFromPassword

Password-bound (v2) KEK derived from the raw password. Because the password is never stored, a database dump plus DB_ENCRYPTION_KEY cannot unwrap the DATA_KEY — this is what binds attendee PII at rest to the account password.

f
encrypt

Encrypt a string value using AES-256-GCM via node:crypto (faster than Web Crypto for the small payloads this handles; output stays interoperable). Returns format: enc:1:$base64iv:$base64ciphertext Note: ciphertext includes the GCM auth tag appended.

f
encryptBytes

Encrypt binary data with AES-256-GCM using compact binary format. Output: ENCB + version byte + 12-byte IV + ciphertext (with GCM auth tag). Overhead is only 33 bytes (vs ~76% bloat in the legacy text format).

f
encryptWithKey

Encrypt data with a symmetric key (for wrapping private key with DATA_KEY)

f
encryptWithOwnerKey

Encrypt a value with the site owner's public key (hybrid RSA+AES). Only the owner's password-derived private key can decrypt it. Used for attendee PII, email-preference blobs, and bulk-email drafts/templates. Can be called without authentication (e.g. from public ticket forms).

f
formatPrefixed

Format IV + ciphertext as a prefixed base64 string

f
fromBase64

Convert base64 string to Uint8Array

f
fromBase64Url

Convert a base64url string (no padding) back to a Uint8Array — the inverse of toBase64Url.

f
generateDataKey

Generate a random 256-bit symmetric key for data encryption

f
generateKeyPair

Generate an RSA key pair for asymmetric encryption Returns { publicKey, privateKey } as exportable JWK strings

f
generateSecureToken

Generate a cryptographically secure random token Uses Web Crypto API getRandomValues

f
generateTicketToken

Generate a 5-byte uppercase hex ticket token for public ticket URLs

f
getCurrentCsrfToken

Get the most recently generated CSRF token (for synchronous JSX rendering)

f
getEncryptionKeyBytes

Raw 256-bit encryption key bytes, decoded once from DB_ENCRYPTION_KEY

f
getEncryptionKeyString

Get the encryption key bytes from environment variable (sync validation only) Expects DB_ENCRYPTION_KEY to be a base64-encoded 256-bit (32 byte) key

f
getPbkdf2Iterations
No documentation available
f
getPrivateKeyFromSession

Derive the private key from session credentials Used to decrypt attendee PII in admin views Results are cached per session token for 10 seconds

f
getRandomBytes

Generate random bytes using Web Crypto API

f
hashPassword

Hash a password using PBKDF2 Returns format: pbkdf2:iterations:$base64salt:$base64hash

f
hashSessionToken

Hash a session token using SHA-256 Used to store session lookups without exposing the actual token

f
hmacHash
No documentation available
f
hmacHashSync

HMAC-SHA256 hash using DB_ENCRYPTION_KEY Used for blind indexes and hashing limited keyspace values Returns deterministic output for same input (unlike encrypt)

f
hmacSha256Hex

Hex-encoded HMAC-SHA256 of a UTF-8 message under the given secret.

f
hmacToBase64

Convert ArrayBuffer to base64 string

f
hmacToHex

Convert ArrayBuffer to hex string

f
hybridDecrypt

Decrypt data using hybrid encryption Expects format: hyb:1:$base64WrappedKey:$base64iv:$base64ciphertext Results are cached in a bounded LRU (ciphertext -> plaintext)

f
hybridEncrypt

Encrypt data using hybrid encryption (RSA + AES)

f
importPrivateKey

Import a private key from JWK string

f
importPublicKey

Import a public key from JWK string

f
isSignedCsrfToken

Check whether a token uses the signed format

f
onEncryptionKeyChange
No documentation available
f
parseEncryptedPayload

Parse a prefixed encrypted payload into IV and ciphertext bytes. Validates the prefix and separator; throws on invalid format.

f
runWithCsrfContext

Run a function within a CSRF-token scope (one container per request)

f
secureCompare

Constant-time string comparison (over UTF-16 char codes) to prevent timing attacks. Shares the one constant-time loop in constantTimeCodesEqual.

f
setEncryptionKeyForTest

Explicitly set or clear the encryption key for testing. Bypasses Deno.env to avoid races between parallel test workers. Clears every crypto cache, including any registered by onEncryptionKeyChange.

f
setFastPbkdf2ForTest

Explicitly enable/disable fast PBKDF2 for testing without env var races

f
setRsaKeySizeForTest

Explicitly set RSA key size for testing without env var races

f
signCsrfToken

Create a signed CSRF token: s1.{timestamp}.{nonce}.{hmac}

f
symmetricDecrypt

Decrypt a prefixed AES-GCM payload with the given key.

f
symmetricEncrypt

AES-GCM encrypts to enc:1:<base64 iv>:<base64 ciphertext>.

f
toBase64

Convert Uint8Array to base64 string

f
toBase64Url

Convert Uint8Array to base64url string (no padding)

f
unwrapKey

Unwrap a symmetric key Expects format: wk:1:$base64iv:$base64wrapped

f
unwrapSessionDataKey

Unwrap a session's DATA_KEY from its token. An authenticated session that reaches a data-key operation always carries a wrapped data key, so a missing one is a broken invariant — throw rather than invent a key.

f
validateEncryptionKey

Validate encryption key is present and valid Call this on startup to fail fast if key is missing

f
verifyPassword

Verify a password against a hash Uses constant-time comparison to prevent timing attacks

f
verifySignedCsrfToken

Verify a signed CSRF token's signature and expiry

f
wrapDataKeyForPassword

Wrap a DATA_KEY under the password-bound (v2) KEK in one step. The single place new wrapped_data_keys are produced — setup, login migration, invite acceptance, password change, and superuser creation all go through here, so the derive-then-wrap pair lives in exactly one spot.

f
wrapKey

Wrap a symmetric key with another key using AES-GCM Returns format: wk:1:$base64iv:$base64wrapped

Type Aliases

T
AesGcmEncrypted

The IV and ciphertext bytes one AES-GCM encryption produces.

T
WebKeySource

Hands back the Web Crypto key the large-payload path needs. Nothing imports a key until a payload is actually big enough to want one.

Variables

v
AES_KEY_BYTES

Key length AES-256 takes, in bytes.

v
base64ToBase64Url

Convert standard base64 to base64url (no padding). Works on both strings and Uint8Array (bytes are first encoded to base64).

v
ENCRYPTION_PREFIX

Encryption format version prefix Format: enc:1:$base64iv:$base64ciphertext

v
HYBRID_PREFIX

Prefix tagging a hybrid (RSA+AES) ciphertext, e.g. owner-key activity-log messages and attendee PII. Distinguishes them from env-key ENCRYPTION_PREFIX values so a decrypt path can route by format.

v
unwrapKeyWithToken

Unwrap a key using a session token

v
wrapKeyWithToken

Wrap a key using a session token (derives a wrapping key from the token)