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
base64ToBase64Url

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

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 of equal length Caller must ensure arrays have the same length (validated by verifyPassword)

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
importKey

Import a CryptoKey from DB_ENCRYPTION_KEY.

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. Automatically clears all crypto caches (encryption, HMAC, and any registered via 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

Encrypt plaintext with an AES-GCM key, returning prefixed format: enc:1:$base64iv:$base64ciphertext

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
unwrapKeyWithToken

Unwrap a key using a session token

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

f
wrapKeyWithToken

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

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
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.