Something went wrong. Try again.
mirror your GitHub repos to tangled.org automatically synchub.to
mirror sync tangled github git
Something went wrong. Try again.
2.0 kB · 49 lines
TypeScript
at main
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950import crypto from 'node:crypto'import { xchacha20poly1305 } from '@noble/ciphers/chacha.js'
/** * Authenticated encryption with a key from runtime config (`NUXT_ENCRYPTION_KEY`, * base64-encoded 32 bytes). Used to wrap anything sensitive at the app layer * before it lands in the DB: AT Proto session blobs, SSH private keys. * * The KEK is held only in env. If it's lost, every encrypted row becomes * unreadable. KEK rotation is a future concern; see PLAN.md. */const NONCE_BYTES = 24let cachedKey: Uint8Array | undefined
function getKey(): Uint8Array { if (cachedKey) return cachedKey // Read process.env directly rather than via useRuntimeConfig() so this helper // is callable from outside a Nitro request context (e.g. tests, scripts). // Nuxt's runtime config still declares the var for documentation; the env // name is the same. const raw = process.env.NUXT_ENCRYPTION_KEY if (!raw) { throw new Error('NUXT_ENCRYPTION_KEY is not set (expected base64-encoded 32 bytes)') } const decoded = Buffer.from(raw, 'base64') if (decoded.length !== 32) { throw new Error(`NUXT_ENCRYPTION_KEY must decode to 32 bytes, got ${decoded.length}`) } cachedKey = new Uint8Array(decoded) return cachedKey}
export function encrypt(plaintext: string): { ciphertext: Buffer, nonce: Buffer } { const nonce = crypto.randomBytes(NONCE_BYTES) const cipher = xchacha20poly1305(getKey(), new Uint8Array(nonce)) const ciphertext = cipher.encrypt(new TextEncoder().encode(plaintext)) return { ciphertext: Buffer.from(ciphertext), nonce }}
export function decrypt(ciphertext: Buffer, nonce: Buffer): string { const cipher = xchacha20poly1305(getKey(), new Uint8Array(nonce)) const plaintext = cipher.decrypt(new Uint8Array(ciphertext)) return new TextDecoder().decode(plaintext)}
/** Test/utility hook: drop the cached key so the next call re-reads runtime config. */export function clearEncryptionKeyCache() { cachedKey = undefined}