Decrypt Crypto-js encrypted text with key with PHP

Tags: , , , ,



I’m using Crypto-js for encrypting password with a key and send it to server. I want to decrypt it in server using PHP. How this can be done?

JS:

  let encKey = "Secret Passphrase"; 
  let text = "123";
  let iv = CryptoJS.enc.Hex.parse("FgLFXEr1MZl2mEnk");
  var encryptedText = CryptoJS.AES.encrypt(text, encKey, { iv: iv }).toString();

Encrypted text:

U2FsdGVkX1+EaW3J1GE1k/EU5h6C+nxBH364Xhez+b0=

PHP:

<?php
$strg  =  "U2FsdGVkX1+EaW3J1GE1k/EU5h6C+nxBH364Xhez+b0=";
$encryptedstrings  =  base64_decode($strg);
$encryptionMethod  =  'aes-256-cbc';
$key  =  "Secret Passphrase";
$iv  =  "FgLFXEr1MZl2mEnk";
  
$rawText   = openssl_decrypt($encryptedstrings, $encryptionMethod, $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING , $iv);

var_dump($rawText);

Result:

string(32) “����>���s��ȡ�V?E��M���I”

I’m getting weird results here.

Answer

The following solution is not from my side but from @Artjom B., so all credits go to him. You will find the source here: https://stackoverflow.com/a/27678978/8166854.

To your problem: you run the CryptoJs encryption with a passphrase and not with a key. According to the docs (https://cryptojs.gitbook.io/docs/#the-cipher-algorithms) section cipher algorithms the (internal AES) key is derived from the passphrase with an outdated and unsecure function that should no longer be in use.

Artjom B. was able to make this key derivation available on PHP. As a side note: it is not necessary to present an initialization vector (IV) to the encryption function as the IV is as well derived from the passphrase, so I’m leaving it out in the following code.

This is the result on PHP-side:

solution for https://stackoverflow.com/questions/65234428/decrypt-crypto-js-encrypted-text-with-key-with-php
string(3) "123"
decryptedtext: 123

This is the code, please obey the warning: This code is provided for achieve compatibility between different programming languages. It is not necessarily fully secure. Its security depends on the complexity and length of the password, because of only one iteration and the use of MD5. I would recommend to use at least a 20 character password with alphanumeric characters which is ideally randomly generated.

<?php

/*
source: https://stackoverflow.com/a/27678978/8166854 author: Artjom B.
Security notice: This code is provided for achieve compatibility between different programming languages.
It is not necessarily fully secure. Its security depends on the complexity and length of the password,
because of only one iteration and the use of MD5. I would recommend to use at least a 20 character password
with alphanumeric characters which is ideally randomly generated.
 */

function evpKDF($password, $salt, $keySize = 8, $ivSize = 4, $iterations = 1, $hashAlgorithm = "md5") {
    $targetKeySize = $keySize + $ivSize;
    $derivedBytes = "";
    $numberOfDerivedWords = 0;
    $block = NULL;
    $hasher = hash_init($hashAlgorithm);
    while ($numberOfDerivedWords < $targetKeySize) {
        if ($block != NULL) {
            hash_update($hasher, $block);
        }
        hash_update($hasher, $password);
        hash_update($hasher, $salt);
        $block = hash_final($hasher, TRUE);
        $hasher = hash_init($hashAlgorithm);
        // Iterations
        for ($i = 1; $i < $iterations; $i++) {
            hash_update($hasher, $block);
            $block = hash_final($hasher, TRUE);
            $hasher = hash_init($hashAlgorithm);
        }
        $derivedBytes .= substr($block, 0, min(strlen($block), ($targetKeySize - $numberOfDerivedWords) * 4));
        $numberOfDerivedWords += strlen($block)/4;
    }
    return array(
        "key" => substr($derivedBytes, 0, $keySize * 4),
        "iv"  => substr($derivedBytes, $keySize * 4, $ivSize * 4)
    );
}

function decrypt($ciphertext, $password) {
    $ciphertext = base64_decode($ciphertext);
    if (substr($ciphertext, 0, 8) != "Salted__") {
        return false;
    }
    $salt = substr($ciphertext, 8, 8);
    $keyAndIV = evpKDF($password, $salt);
    $decryptPassword = openssl_decrypt(
        substr($ciphertext, 16),
        "aes-256-cbc",
        $keyAndIV["key"],
        OPENSSL_RAW_DATA, // base64 was already decoded
        $keyAndIV["iv"]);
    return $decryptPassword;
}

echo 'solution for https://stackoverflow.com/questions/65234428/decrypt-crypto-js-encrypted-text-with-key-with-php' . PHP_EOL;
$key  =  "Secret Passphrase";
$strg = "U2FsdGVkX1+EaW3J1GE1k/EU5h6C+nxBH364Xhez+b0=";
$rawText = decrypt($strg, $key);
var_dump($rawText);
echo 'decryptedtext: ' . $rawText . PHP_EOL;
?>


Source: stackoverflow