2

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.

3
  • The beginning of your ciphertext U2FsdGVkX1 indicates that the key material was passed as string during encryption. In this case CryptoJS applies a key derivation function (EVP_BytesToKey()), which is not a standard and has to be implemented explicitly in the PHP code (you can find PHP implementations on the web). The at once is not clear to me, you have to decrypt each ciphertext with its corresponding key individually. Commented Sep 20, 2022 at 13:33
  • @Topaco thank you for your reply. The at once part i will do. I am facing a problem in creating a PHP function to decrypt it. I even tried to read about EVP_BytesToKey() as you mentioned, but I am unable to figure out how to implement it in PHP. For e.g. if I want to decrypt U2FsdGVkX1+cBvU9yH5fIGVmliJYPXsv4AIosUGH4tA= with its key earth, what should be my PHP code. Commented Sep 20, 2022 at 14:09
  • Please see my answer. Commented Sep 20, 2022 at 15:36

1 Answer 1

1

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;
} 
?>
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you very much for your prompt reply. I was unable to find out how to determine key and iv. Your code sample helped me understand quite a few new things .

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.