Search code examples
javascriptphpaescryptojs

openssl_encrypt cipher decypted using Crypto JS


I have a custom payment method on WordPress that processes the payment through a NodeJS API. For obvious reasons, I should encrypt some data, like credit card numbers and cvv2s.

This is how I encrypt my fields in PHP:

        $cvv2 = openssl_encrypt(
        $_POST['cvv2'], 
        'AES-256-CBC',
        "2c2702d12c747661358dfe9b77425628", // Testing key, thats why its set like this
        0
    );

This is the output ciphered text: CRqJRoqHriB7X/u1bwSE1Q==

This is how I try to decrypt in JS

const key = "2cea02d12c747661358dfe9b77425628";

const dec = CryptoJS.AES.decrypt(cvv2,key);

console.log(dec.toString(CryptoJS.enc.Utf8))

But the output is always an empty string.

This is me decrypting it using an online tool

enter image description here

I am really frustrated as I cannot seem to make this work, no matter how much I read online. What could be the problem?


Solution

  • In the CryptoJS code, the key must be passed as WordArray (using a suitable encoder) and the zero IV (16 0x00 values) used implicitly in the PHP code must be specified explicitly.
    The ciphertext must be passed as CipherParams object or Base64 encoded (the latter is implicitly converted to a CipherParams object):

    const key = CryptoJS.enc.Utf8.parse("2cea02d12c747661358dfe9b77425628");
    const iv = CryptoJS.lib.WordArray.create([], 16);
    const ciphertext = "CRqJRoqHriB7X/u1bwSE1Q==";
    
    const dec = CryptoJS.AES.decrypt(ciphertext, key, {iv:  iv});
    
    console.log(dec.toString(CryptoJS.enc.Base64));
    console.log(dec.toString(CryptoJS.enc.Utf8));
    <script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js"></script>

    Note that a static IV is insecure.