Home > Enterprise >  Decrypt crypt-js encrypted string in PHP
Decrypt crypt-js encrypted string in PHP

Time:09-21

I have encrypted mutiple strings one-by-one in using crypto-js in react.'

For encryption I used -

encryptAES = (text, key) => {
    return CryptoJS.AES.encrypt(text, key).toString();
};

For decryption, I used function like following -

decryptAES = (encryptedBase64, key) => {
    const decrypted = CryptoJS.AES.decrypt(encryptedBase64, key);
    if (decrypted) {
      try {
        console.log(decrypted);
        const str = decrypted.toString(CryptoJS.enc.Utf8);
        if (str.length > 0) {
          return str;
        } else {
          return 'error 1';
        } 
      } catch (e) {
        return 'error 2';
      }
    }
    return 'error 3';
  };

I have uploaded a working sample project of this encryption - decryption here.

For e.g., if I encrypt "I live in India" using key - "earth", it would output as - "U2FsdGVkX1 cBvU9yH5fIGVmliJYPXsv4AIosUGH4tA=", and similary it would decrypt successfully with the correct key.

Now I have multiple encrypted strings stored in my database, but now require them to store un-encrypted, so I wanted to decrypt them in PHP. I can decrypt them in js using the function mentioned above but I am unable to figure out how to do so in PHP. I have tried this github repository but I couldn't customize it for my use case.

CodePudding user response:

For decryption, salt and ciphertext must first be determined. To do this, the encrypted data of the CryptoJS code must be Base64 decoded. The salt are the second 8 bytes of the Base64 decoded data, followed by the actual ciphertext (the first 8 bytes are the ASCII encoding of Salted__ and can be ignored).

After determining the salt, key and IV are to be derived with EVP_BytesToKey(). You can find various PHP implementations on the web, e.g. here. Note that CryptoJS uses MD5 as digest, so the digest in the linked code must be modified accordingly.

Once key and IV have been determined, the actual ciphertext can be decrypted.

All together:

<?php
// Separate salt and actual ciphertext
$ctOpenSSL = base64_decode("U2FsdGVkX1 cBvU9yH5fIGVmliJYPXsv4AIosUGH4tA=");
$salt = substr($ctOpenSSL, 8, 8);
$ciphertext = substr($ctOpenSSL, 16);

// Derive key and IV
$keyIv = EVP_BytesToKey($salt, "earth");
$key = substr($keyIv, 0, 32);
$iv = substr($keyIv, 32, 16);

// Decrypt
$decrypted = openssl_decrypt($ciphertext, "aes-256-cbc", $key, OPENSSL_RAW_DATA, $iv);
print($decrypted . PHP_EOL); // I live in India

function EVP_BytesToKey($salt, $password) {
    $bytes = '';
    $last = '';
    while(strlen($bytes) < 48) {
        $last = hash('md5', $last . $password . $salt, true);
        $bytes.= $last;
    }
    return $bytes;
} 
?>
  • Related