Message d’erreur
Malformed UTF-8 data
CryptoJS — thrown by .toString(CryptoJS.enc.Utf8) after decrypt
Ce que cela signifie
CryptoJS a déchiffré votre texte chiffré en octets qui ne forment pas de l’UTF-8 valide, et leur conversion en chaîne a échoué. Comme l’AES de CryptoJS (mode CBC) n’a aucun contrôle d’intégrité, une mauvaise clé ne fait pas échouer le déchiffrement : elle produit simplement des octets aléatoires, et le décodeur UTF-8 est le premier à s’en apercevoir. La même mauvaise clé peut aussi donner une chaîne vide au lieu de cette erreur (lorsque la vérification du remplissage échoue proprement, par hasard) : les deux symptômes relèvent donc d’un même diagnostic.
Pourquoi cela se produit
Mauvaise clé ou phrase de passe
fréquenteDéchiffrer avec une clé différente de celle du chiffrement produit une sortie pseudo-aléatoire. Le symptôme obtenu dépend de la longueur du message : lors de notre test, environ un déchiffrement sur huit avec une mauvaise clé a levé cette erreur pour un message de 29 octets, environ la moitié pour un message de 100 octets et la totalité pour 300 octets ; presque tous les autres ont renvoyé une chaîne vide. Dans les deux cas, c’est la clé qu’il faut soupçonner.
Dérivation de clé différente des deux côtés
fréquenteCryptoJS.AES.encrypt(msg, "passphrase") dérive la clé et l’IV via une KDF compatible OpenSSL avec un sel aléatoire. Si l’autre côté traite la phrase de passe comme une clé brute (ou si une autre plateforme déchiffre sans cette KDF), les clés dérivées diffèrent et la sortie est inexploitable.
Texte chiffré corrompu pendant le transport
occasionnelleDu Base64 altéré par l’encodage URL (le + transformé en espace), une troncature au stockage ou un double encodage modifie les octets du texte chiffré ; le déchiffrement CBC d’octets altérés produit des données inexploitables sans la moindre erreur au niveau de la couche cryptographique.
Comment corriger l’erreur
- 1.
Rendre la gestion des clés explicite et symétrique
Évitez l’ambiguïté de la KDF appliquée à la phrase de passe : passez une vraie clé sous forme de WordArray avec un IV explicite, de manière identique des deux côtés.
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.
Traiter une sortie vide comme le même échec
Vérifiez le résultat et remontez une vraie erreur : des chaînes vides silencieuses masquent pendant des mois les bugs de mauvaise clé.
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.
Préférer un schéma authentifié
L’AES-GCM de WebCrypto authentifie le texte chiffré : une mauvaise clé échoue de façon visible et déterministe au lieu de produire des données inexploitables, ce qui élimine entièrement cette classe d’erreurs.
js const pt = await crypto.subtle.decrypt({ name: "AES-GCM", iv }, key, ct); // wrong key → OperationError, never silent garbage