(raw: string)
| 17 | const CIPHER_ALGORITHM = "aes-256-gcm"; |
| 18 | |
| 19 | const decodeKey = (raw: string): Buffer => { |
| 20 | if (raw === "") { |
| 21 | throw ApiErrors.internal( |
| 22 | "MFA_ENCRYPTION_KEY is empty. Generate one with `openssl rand -base64 32` and set it before enabling MFA." |
| 23 | ); |
| 24 | } |
| 25 | |
| 26 | let key: Buffer; |
| 27 | |
| 28 | try { |
| 29 | key = Buffer.from(raw, "base64"); |
| 30 | } catch { |
| 31 | throw ApiErrors.internal( |
| 32 | "MFA_ENCRYPTION_KEY is not valid base64. Generate a fresh key with `openssl rand -base64 32`." |
| 33 | ); |
| 34 | } |
| 35 | |
| 36 | if (key.length !== AES_256_KEY_BYTES) { |
| 37 | throw ApiErrors.internal( |
| 38 | `MFA_ENCRYPTION_KEY decoded to ${String(key.length)} bytes; expected ${String( |
| 39 | AES_256_KEY_BYTES |
| 40 | )}. Regenerate with \`openssl rand -base64 32\`.` |
| 41 | ); |
| 42 | } |
| 43 | |
| 44 | return key; |
| 45 | }; |
| 46 | |
| 47 | /** |
| 48 | * AES-256-GCM string encryption with a versioned ciphertext format. |
no outgoing calls
no test coverage detected