mirror your GitHub repos to tangled.org automatically
1

Configure Feed

Select the types of activity you want to include in your feed.

1import crypto from 'node:crypto' 2import { xchacha20poly1305 } from '@noble/ciphers/chacha.js' 3 4/** 5 * Authenticated encryption with a key from runtime config (`NUXT_ENCRYPTION_KEY`, 6 * base64-encoded 32 bytes). Used to wrap anything sensitive at the app layer 7 * before it lands in the DB: AT Proto session blobs, SSH private keys. 8 * 9 * The KEK is held only in env. If it's lost, every encrypted row becomes 10 * unreadable. KEK rotation is a future concern \u2014 see PLAN.md. 11 */ 12const NONCE_BYTES = 24 13let cachedKey: Uint8Array | undefined 14 15function getKey(): Uint8Array { 16 if (cachedKey) return cachedKey 17 // Read process.env directly rather than via useRuntimeConfig() so this helper 18 // is callable from outside a Nitro request context (e.g. tests, scripts). 19 // Nuxt's runtime config still declares the var for documentation; the env 20 // name is the same. 21 const raw = process.env.NUXT_ENCRYPTION_KEY 22 if (!raw) { 23 throw new Error('NUXT_ENCRYPTION_KEY is not set (expected base64-encoded 32 bytes)') 24 } 25 const decoded = Buffer.from(raw, 'base64') 26 if (decoded.length !== 32) { 27 throw new Error(`NUXT_ENCRYPTION_KEY must decode to 32 bytes, got ${decoded.length}`) 28 } 29 cachedKey = new Uint8Array(decoded) 30 return cachedKey 31} 32 33export function encrypt(plaintext: string): { ciphertext: Buffer, nonce: Buffer } { 34 const nonce = crypto.randomBytes(NONCE_BYTES) 35 const cipher = xchacha20poly1305(getKey(), new Uint8Array(nonce)) 36 const ciphertext = cipher.encrypt(new TextEncoder().encode(plaintext)) 37 return { ciphertext: Buffer.from(ciphertext), nonce } 38} 39 40export function decrypt(ciphertext: Buffer, nonce: Buffer): string { 41 const cipher = xchacha20poly1305(getKey(), new Uint8Array(nonce)) 42 const plaintext = cipher.decrypt(new Uint8Array(ciphertext)) 43 return new TextDecoder().decode(plaintext) 44} 45 46/** Test/utility hook: drop the cached key so the next call re-reads runtime config. */ 47export function clearEncryptionKeyCache() { 48 cachedKey = undefined 49}