2

I want to encrypt and decrypt a value using crypto-js but I am getting Malformed UTF-8 data on decryption. Here's my code : Encryption part:

      const keyUTF = CryptoJS.enc.Utf8.parse(SECRET_KEY);
      const iv = CryptoJS.enc.Base64.parse(SECRET_KEY);
      const tokenKey = getTokenKey();
      const encryptedToken = CryptoJS.AES.encrypt(
        JSON.stringify({ token }),
        keyUTF,
        {
          iv,
          // mode: CryptoJS.mode.CBC,
          // padding: CryptoJS.pad.Pkcs7,
        }
      ).toString();
      console.log("Token:", tokenKey, encryptedToken);

Decryption Part:

const keyUTF = CryptoJS.enc.Utf8.parse(SECRET_KEY);
  const iv = CryptoJS.enc.Base64.parse(SECRET_KEY);
  const tokenKey = getTokenKey();
  const encryptedToken = cookies.get(tokenKey);
  console.log(tokenKey, encryptedToken);
  let decryptedToken;
  if (encryptedToken) {
    // console.log(encryptedToken, encryptedToken.toString(CryptoJS.enc.Utf8));
    decryptedToken = CryptoJS.AES.decrypt(encryptedToken.toString(), keyUTF, {
      iv,
    }).toString(CryptoJS.enc.Utf8);
    console.log("Decrypted :", decryptedToken.toString());
  }

I have looked at multiple questions related to this and tried all of their solutions but I still get the error. I have tried:

  • Passing an object as {ciphertext:value} to the decrypt function
  • Using JSON.stringify with both the string and as an object(in current code)
  • Passed mode and padding to encrypt/decrypt function (commented out)
Abdullah Razzaki
  • 972
  • 8
  • 16
  • I can't reproduce this on my machine, please post sample data. Check if `cookies.get(tokenKey)` really contains the correct data. For encryption, `token` is not defined (probably a copy/paste error and `tokenKey` is meant). – Topaco May 26 '21 at 09:27
  • 1
    I believe this https://stackoverflow.com/questions/29512858/cryptojs-and-key-iv-length answers your question. – aleksxor May 26 '21 at 10:06
  • This is probably due to the ciphertext being affected by `toString`. Use explicit base 64 encoding / decoding of the ciphertext to see if that changes things. The IV should be random and included with the ciphertext. If you are using above in a client / server setting you're doomed by the way: **use TLS**. – Maarten Bodewes May 26 '21 at 10:21
  • 1
    If you derive the key with a UTF-8 encoding and the IV with a Base64 decoding from the _same_ `SECRET_KEY`, then this should generally result in either an invalid key or an invalid IV (CryptoJS handles invalid IVs and (some) invalid keys, but in general the result is not AES compliant and can only be decrypted by CryproJS). The only valid combination I can see would be if `SECRET_KEY` is a 24 bytes Base64 string. This would correspond to a 24 bytes key (AES-192) and a 16 bytes iv. It would make more sense to decouple key and iv. – Topaco May 26 '21 at 12:40
  • @Topaco yes I have done that now Thanks – Abdullah Razzaki May 26 '21 at 13:21

0 Answers0