使用Crypto-JS解密JSON字符串时遇Malformed UTF-8 data错误求助
Let's break down why you're hitting this error and how to fix it. The "Malformed UTF-8 data" message typically pops up when the decrypted WordArray from CryptoJS can't be converted to valid UTF-8 text—usually because the decryption process failed (e.g., corrupted data, mismatched keys) or the encrypted string was messed up during transmission.
Root Causes to Check
- Corrupted Encrypted String During Upload: If your encrypted string gets modified mid-transmission (extra spaces, URL encoding glitches, truncated characters), CryptoJS can't decrypt it properly, leading to invalid UTF-8 data.
- Mismatched Keys: Even a tiny difference in the encryption/decryption key (case, extra spaces, encoding) will break decryption.
- Missing Error Handling: Your current decrypt function doesn't verify if decryption succeeded before trying to convert to UTF-8, so invalid data throws an unhandled error.
Step-by-Step Solutions
1. Update the Decrypt Function with Validation
Add checks to catch failed decryption early and handle it gracefully:
function decrypt(data, key) { try { const decryptedWordArray = CryptoJS.AES.decrypt(data, key); // Check if decryption produced valid data if (decryptedWordArray.sigBytes <= 0) { throw new Error("Invalid encrypted data or mismatched key"); } const plaintext = decryptedWordArray.toString(CryptoJS.enc.Utf8); // Verify the plaintext is valid UTF-8 if (!plaintext) { throw new Error("Malformed UTF-8 data after decryption"); } return plaintext; } catch (error) { console.error("CryptoJS decryption Error:", error.message); throw error; // Re-throw or return null based on your needs } }
2. Securely Transmit the Encrypted String
Use URL encoding to prevent corruption during upload/download. Adjust your flow like this:
// Before uploading const encryptedString = encrypt(jsonStr, "testkey"); const safeEncryptedString = encodeURIComponent(encryptedString); // After receiving the string const receivedEncryptedString = decodeURIComponent(safeEncryptedString); const decryptedJson = decrypt(receivedEncryptedString, "testkey");
3. Validate Decrypted JSON Before Parsing
Once you get the decrypted string, confirm it's valid JSON before parsing:
const decryptedStr = decrypt(receivedEncryptedString, "testkey"); try { const originalArray = JSON.parse(decryptedStr); console.log("Restored array:", originalArray); } catch (parseError) { console.error("Failed to parse JSON:", parseError.message); }
4. Confirm Key Consistency
Ensure the decryption key is exactly the same as the encryption key—no typos, case differences, or extra whitespace. If the key comes from an external source (like a backend), confirm it's encoded in UTF-8 (CryptoJS uses UTF-8 by default for string keys).
Quick Test to Verify Core Functionality
Run this snippet to rule out issues with your basic encryption/decryption logic:
const testArray = [{test:1},{test:2}]; const jsonStr = JSON.stringify(testArray); const encrypted = encrypt(jsonStr, "testkey"); const decrypted = decrypt(encrypted, "testkey"); const parsed = JSON.parse(decrypted); console.log("Original:", testArray); console.log("Restored:", parsed);
If this works, the problem is almost certainly with how you're transmitting the encrypted string.
内容的提问来源于stack exchange,提问作者user2112417

