跳到主要内容
ecdsa.com
CryptoJS其他工具

错误信息

Malformed UTF-8 data

CryptoJS — thrown by .toString(CryptoJS.enc.Utf8) after decrypt

含义

CryptoJS 把你的密文解密成了不是合法 UTF-8 的字节,把它们转换为字符串时失败了。由于 CryptoJS 的 AES(CBC 模式)没有完整性校验,密钥错误并不会让解密失败——只会产生随机字节,而 UTF-8 解码器是第一个察觉问题的环节。同样是密钥错误,也可能不出现这个错误,而是得到空字符串(填充检查恰好明确失败时),因此这两种症状的诊断是一样的。

原因

修复方法

  1. 1.

    显式处理密钥,两端保持一致

    避开密码短语 KDF 带来的歧义:以 WordArray 形式传入真正的密钥,并显式提供 IV,两端的做法完全相同。

    js
    const key = CryptoJS.enc.Hex.parse(hexKey);        // 32-byte key, both sides
    const iv  = CryptoJS.enc.Hex.parse(hexIv);         // 16-byte IV, both sides
    const ct  = CryptoJS.AES.encrypt(plaintext, key, { iv });
    const pt  = CryptoJS.AES.decrypt(ct.toString(), key, { iv })
                  .toString(CryptoJS.enc.Utf8);
  2. 2.

    把空输出视为同一种失败

    检查结果,并明确报出错误——静默返回的空字符串会把密钥错误的 bug 掩盖好几个月。

    js
    const pt = CryptoJS.AES.decrypt(ct, key, { iv }).toString(CryptoJS.enc.Utf8);
    if (!pt) throw new Error("decryption failed: wrong key/IV or corrupted ciphertext");
  3. 3.

    优先使用认证加密方案

    WebCrypto 的 AES-GCM 会对密文做认证:密钥错误时,解密每次都会明确失败,而不是产生乱码——从而彻底消除这一类错误。

    js
    const pt = await crypto.subtle.decrypt({ name: "AES-GCM", iv }, key, ct);
    // wrong key → OperationError, never silent garbage

相关错误

浏览完整的签名错误库