October 27, 2024
Chicago 12, Melborne City, USA
javascript

Encrypt with PHP, Decrypt with Javascript (AES-CBC)


I want to encrypt something in PHP and decrypt it in JavaScript.

My problem is that I’m getting an "Error decrypting: OperationError" when trying to decrypt in JS, but no more hints what might be wrong.

I broke it down to a testfile like this, perhaps someone got an idea what the problem might be?

<?php
    
    $sKey = "RscFrKLJaAdEFF5Kcp1ShY5xsTu3AKisdaxIggioiks="; // already base64_encoded
        
    $cipher = "AES-256-CBC";
    $ivlen = openssl_cipher_iv_length($cipher); // 16 Bytes
    $iv = openssl_random_pseudo_bytes($ivlen);

    $sPlainTxt = "My encrypted text";
    $sEncoded = openssl_encrypt($sPlainTxt, $cipher, $sKey, OPENSSL_RAW_DATA, $iv);
   
    // Just to test if it's possible to decrypt again in PHP
    $sDecodedTxt = openssl_decrypt($sEncoded, $cipher, $sKey, OPENSSL_RAW_DATA, $iv); // This works
?>

<script>
$(document).ready(function() {
    var encryptedString = "<?php print base64_encode($iv.$sEncoded); ?>";
    
    decryptString(encryptedString, '<?php print $sKey;?>').then(result=> {
            if (result!== null)
            {   // Show result
                console.log(result);
            }
        }).catch(error => {
            console.log("Error");
        });
});

async function decryptString(encryptedString, key) {
    
    const keyBytes = Uint8Array.from(atob(key), c => c.charCodeAt(0)); // Base64    
    const keyBuffer = keyBytes.buffer;

    const keyMaterial = await window.crypto.subtle.importKey(
        "raw",
        keyBuffer,
        { name: "AES-CBC" },
        false,
        ["decrypt"]
    );

    const encryptedData = Uint8Array.from(atob(encryptedString), c => c.charCodeAt(0)); // Base64

    // extract IV and Ciphertext 
    const iv = encryptedData.slice(0, 16); // First 16 bytes contain iv
    const ciphertext = encryptedData.slice(16); // the rest is ciphertext
    
    try {
        const decrypted = await window.crypto.subtle.decrypt(
            { name: "AES-CBC", iv },
            keyMaterial,
            ciphertext
        );

        return new TextDecoder().decode(decrypted);
        
    } catch (e) {
        console.error("Error decrypting:", e);
        return null;
    }
}
</script>

P.S.: I know this is no "high security"-operation, it’s more to obfuscate some things from spam-bots. Might be that AES is a bit "big" for that, but it seems to be there so I thought I might even use it.



You need to sign in to view this answers

Leave feedback about this

  • Quality
  • Price
  • Service

PROS

+
Add Field

CONS

+
Add Field
Choose Image
Choose Video