From 515a461bbfd615127b8511d7f87a1fc7c4368068 Mon Sep 17 00:00:00 2001 From: Ajax Davis Date: Sat, 3 Jan 2026 19:20:07 +1000 Subject: [PATCH] fix: add helpful error message for API key decryption failure --- apps/web/src/lib/crypto/api-keys.ts | 30 ++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/apps/web/src/lib/crypto/api-keys.ts b/apps/web/src/lib/crypto/api-keys.ts index 8065ce6..c6239dd 100644 --- a/apps/web/src/lib/crypto/api-keys.ts +++ b/apps/web/src/lib/crypto/api-keys.ts @@ -35,19 +35,31 @@ export function encryptApiKey(apiKey: string): { encrypted: string; iv: string } * Decrypts an API key using AES-256-GCM */ export function decryptApiKey(encrypted: string, iv: string): string { - const key = getEncryptionKey(); + try { + const key = getEncryptionKey(); - // Extract the auth tag (last 32 hex chars = 16 bytes) - const authTag = Buffer.from(encrypted.slice(-32), 'hex'); - const encryptedData = encrypted.slice(0, -32); + // Extract the auth tag (last 32 hex chars = 16 bytes) + const authTag = Buffer.from(encrypted.slice(-32), 'hex'); + const encryptedData = encrypted.slice(0, -32); - const decipher = createDecipheriv(ALGORITHM, key, Buffer.from(iv, 'hex')); - decipher.setAuthTag(authTag); + const decipher = createDecipheriv(ALGORITHM, key, Buffer.from(iv, 'hex')); + decipher.setAuthTag(authTag); - let decrypted = decipher.update(encryptedData, 'hex', 'utf8'); - decrypted += decipher.final('utf8'); + let decrypted = decipher.update(encryptedData, 'hex', 'utf8'); + decrypted += decipher.final('utf8'); - return decrypted; + return decrypted; + } catch (error) { + // Provide a more helpful error message + const message = error instanceof Error ? error.message : 'Unknown error'; + if (message.includes('Unsupported state') || message.includes('unable to authenticate')) { + throw new Error( + 'API key decryption failed. The encryption secret may have changed. ' + + 'Please re-save your API key in Settings > API Keys.' + ); + } + throw error; + } } /**