From 848f4b51d205f987309365741c2b31dbad0846c8 Mon Sep 17 00:00:00 2001 From: zhangxiang Date: Mon, 3 Aug 2026 10:39:51 +0800 Subject: [PATCH] fix(crypto): align server-side encrypted format with client-side Web Crypto API The server-side encrypt function in crypto-server.ts used format `iv + authTag + encrypted`, but the client-side decrypt function in crypto.ts expects `iv + encrypted + authTag` (authTag at the end, matching Web Crypto API convention where ciphertext includes authTag). This mismatch caused all admin API requests to fail with "The operation failed for an operation-specific reason" when NEXT_PUBLIC_ENCRYPTION_SECRET was configured, since the client could not decrypt the server's response. Fix: swap the order of authTag and encrypted in both encrypt and decrypt functions in crypto-server.ts. --- src/lib/crypto-server.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/lib/crypto-server.ts b/src/lib/crypto-server.ts index 237d31e..8ad695f 100644 --- a/src/lib/crypto-server.ts +++ b/src/lib/crypto-server.ts @@ -53,8 +53,9 @@ export function encrypt(plaintext: string): string { ]); const authTag = cipher.getAuthTag(); - // 格式: iv + authTag + encrypted - const combined = Buffer.concat([iv, authTag, encrypted]); + // 格式: iv + encrypted + authTag + // 与客户端 crypto.ts 的 decrypt 格式一致(Web Crypto API 将 authTag 附在 ciphertext 末尾) + const combined = Buffer.concat([iv, encrypted, authTag]); return combined.toString('base64'); } @@ -66,8 +67,8 @@ export function decrypt(encryptedBase64: string): string { const combined = Buffer.from(encryptedBase64, 'base64'); const iv = combined.subarray(0, IV_LENGTH); - const authTag = combined.subarray(IV_LENGTH, IV_LENGTH + AUTH_TAG_LENGTH); - const encrypted = combined.subarray(IV_LENGTH + AUTH_TAG_LENGTH); + const authTag = combined.subarray(combined.length - AUTH_TAG_LENGTH); + const encrypted = combined.subarray(IV_LENGTH, combined.length - AUTH_TAG_LENGTH); const decipher = crypto.createDecipheriv(ALGORITHM, key, iv); decipher.setAuthTag(authTag);