| 184 | * Format: iv:authTag:encrypted (all base64) |
| 185 | */ |
| 186 | export function encryptWithSymmetricKey(value: string, keyBase64: string): string { |
| 187 | if (!keyBase64) { |
| 188 | throw new EncryptionConfigurationError('Encryption key is required'); |
| 189 | } |
| 190 | |
| 191 | const key = Buffer.from(keyBase64, 'base64'); |
| 192 | if (key.length !== 32) { |
| 193 | throw new EncryptionConfigurationError('Encryption key must be exactly 32 bytes (256 bits)'); |
| 194 | } |
| 195 | |
| 196 | const iv = randomBytes(16); |
| 197 | const cipher = createCipheriv('aes-256-gcm', key, iv); |
| 198 | |
| 199 | let encrypted = cipher.update(value, 'utf8', 'base64'); |
| 200 | encrypted += cipher.final('base64'); |
| 201 | |
| 202 | const authTag = cipher.getAuthTag(); |
| 203 | |
| 204 | return `${iv.toString('base64')}:${authTag.toString('base64')}:${encrypted}`; |
| 205 | } |
| 206 | |
| 207 | /** |
| 208 | * Decrypts a value encrypted with encryptWithSymmetricKey. |