shorif2000
shorif2000

Reputation: 2654

how to convert openssl encrypt and decrypt into php

I am trying to convert the following shell commands into php but I ma not getting correct results

$key = 'my_key';

    $cmd = "echo -n $plaintext| openssl enc -e -aes-256-cbc -a -k $key -md md5";
    $exec = exec($cmd, $output, $status);
    return $status == 0 ? $output[0] : null;

the above works in php7.4. I have tried the following

$key = "my_key";
    echo "key: $key\n";
    //$key = password_hash($key, PASSWORD_BCRYPT, ['cost' => 12]);
    //echo "key: $key\n";
    $ciphertext = openssl_encrypt($plaintext, 'aes-256-cbc', $key, null, 'UqA8Z5ztUYnWhnUE');
    echo "ciphertext: $ciphertext\n";
    echo "merged: $key$ciphertext\n";
    return $key . $ciphertext;

This is not working. The key is supplied by 3rd party

UPDATE

I have tried the following

create a key and iv

# openssl enc -nosalt -aes-256-cbc -k hello-aes -P -md md5                                       *** WARNING : deprecated key derivation used.
Using -iter or -pbkdf2 would be better.
key=C639A572E14D5075C526FDDD43E4ECF6B095EA17783D32EF3D2710AF9F359DD4
iv =D09A4D2C5DC39843FE075313A7EF2F4C

on cli I can use the key to encrypt and decrypt

encrypt

# echo -n [email protected] | openssl enc -e -aes-256-cbc -a -k C639A572E14D5075C526FDDD43E4ECF6B095EA17783D32EF3D2710AF9F359DD4 -md md5
*** WARNING : deprecated key derivation used.
Using -iter or -pbkdf2 would be better.
U2FsdGVkX1+GpDPQ5uLeXlZL9CEgKaBDgDuwvf00m9U=

decrypt

# echo U2FsdGVkX1+GpDPQ5uLeXlZL9CEgKaBDgDuwvf00m9U= | openssl enc -d -aes-256-cbc -a -k C639A572E14D5075C526FDDD43E4ECF6B095EA17783D32EF3D2710AF9F359DD4 -md md5
*** WARNING : deprecated key derivation used.
Using -iter or -pbkdf2 would be better.
[email protected]

In PhP

I use the key and iv I created from cli. the key is provided to me i do not get to generate this

function encryptAES256CBC(string $plaintext): string
{
    $key = 'C639A572E14D5075C526FDDD43E4ECF6B095EA17783D32EF3D2710AF9F359DD4';
    //echo "key hex2bin ". md5($key) . "\n\n";
    $iv = hex2bin('D09A4D2C5DC39843FE075313A7EF2F4C');
    echo "key: $key\n";
    $cipher="aes-256-cbc";

    $ciphertext_raw = openssl_encrypt($plaintext, $cipher, $key, $options=OPENSSL_RAW_DATA, $iv);//, null, 'UqA8Z5ztUYnWhnUE');
   
    echo "ciphertext_raw: $ciphertext_raw\n";

    echo "base64_encode: ".base64_encode($ciphertext_raw)."\n";
    echo "base64_encode md5: ".md5(base64_encode($ciphertext_raw))."\n";
    echo "md5: ".md5($ciphertext_raw)."\n";
    return md5($ciphertext_raw);
    return $key . $ciphertext_raw;
}

I tried to decode the above output on cli to check it works but it does not. i get error bad magic number

output

key: C639A572E14D5075C526FDDD43E4ECF6B095EA17783D32EF3D2710AF9F359DD4
ciphertext_raw: y▒▒yV▒ύ2▒G▒▒▒¤▒!▒▒▒%▒"ҋ~▒
base64_encode: B3n1+XlWtM+NMrlHue8R28KkmiG8tpUl/Iwi0ot+vg4=
base64_encode md5: f65b8e0ed4fc86d4b405d37a57bcd6e5
md5: 14e9f14ee94a2c34e52ad80e3f300d40



DECRYPT 14e9f14ee94a2c34e52ad80e3f300d40
 [12:27:43] Destructor
root@0ea89b7ad9df:/# echo 14e9f14ee94a2c34e52ad80e3f300d40 | openssl enc -d -aes-256-cbc -a -k C639A572E14D5075C526FDDD43E4ECF6B095EA17783D32EF3D2710AF9F359DD4 -md md5
bad magic number

UPDATE

I have managed to get decypt working but encrypt not working

this is what I have

$passphrase = 'random';
        $salt = openssl_random_pseudo_bytes(8);
        $keyData = self::evpBytesToKey($salt, $passphrase);
        $key = substr($keyData, 0, 32);
        $iv = substr($keyData, 32, 16);
        $method = 'AES-256-CBC';

        $ciphertext_raw = openssl_encrypt($plaintext, $method, $key, OPENSSL_RAW_DATA, $iv);
        echo "ciphertext_raw: $ciphertext_raw\n";

        echo "base64_encode: ".base64_encode($ciphertext_raw)."\n";
        echo "base64_encode md5: ".md5(base64_encode($ciphertext_raw))."\n";
        echo "md5: ".md5($ciphertext_raw)."\n";
        echo "merged: ".base64_encode($iv.$ciphertext_raw)."\n";
        return md5($ciphertext_raw);

        return base64_encode("Salted__" . $salt . $ciphertext_raw);

Upvotes: 0

Views: 1062

Answers (1)

Michael Fehr
Michael Fehr

Reputation: 6394

The following code is a full running example that uses the "EVP_BytesToKey" key derivation as commented by @Topaco.

Kindly note that this kind of key derivation is UNSECURE as it uses the broken MD5 algorithm and an iteration count of only 1. Please use the code only for migration purpose, thanks.

This is a possible output [as there are random elements your output will differ]:

AES CBC 256 String encryption with passphrase

# # # SECURITY 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.                                        # # #
# # # DO NOT USE THIS CODE IN PRODUCTION                     # # #

passphrase: my secret passphrase

* * * Encryption * * *
ciphertext: U2FsdGVkX1/+hqfCdNaZ36kZzPzwvFXkr4nEySMEgdVdPnPrGUj2Gi1t2pspAH2WHVEVgKHKWfR2Gc0sKnTlLg==
output is (Base64) ciphertext

* * * Decryption * * *
passphrase: my secret passphrase
ciphertext (Base64): U2FsdGVkX19rV+JOoeF72K54jlyJ47tNEsMjih7gDnFUysZFaw+WnYTB5L/hc2+rssFj1hXw3N8kkikHwClB2w==
input is (Base64) ciphertext
plaintext:  The quick brown fox jumps over the lazy dog

code:

<?php
// source: https://github.com/blocktrail/cryptojs-aes-php/blob/master/src/CryptoJSAES.php
// author: BlockTrail
function aesCbcPassphraseEncryptToBase64($passphrase, $data, $salt = null) {
    $salt = $salt ?: openssl_random_pseudo_bytes(8);
    list($key, $iv) = evpkdf($passphrase, $salt);
    $ct = openssl_encrypt($data, 'aes-256-cbc', $key, true, $iv);
    return encode($ct, $salt);
}

function aesCbcPassphraseDecryptFromBase64($passphrase, $base64) {
    list($ct, $salt) = decode($base64);
    list($key, $iv) = evpkdf($passphrase, $salt);
    $data = openssl_decrypt($ct, 'aes-256-cbc', $key, true, $iv);
    return $data;
}

function evpkdf($passphrase, $salt) {
    $salted = '';
    $dx = '';
    while (strlen($salted) < 48) {
        $dx = md5($dx . $passphrase . $salt, true);
        $salted .= $dx;
    }
    $key = substr($salted, 0, 32);
    $iv = substr($salted, 32, 16);
    return [$key, $iv];
}

function decode($base64) {
    $data = base64_decode($base64);
    if (substr($data, 0, 8) !== "Salted__") {
        return "";
    }
    $salt = substr($data, 8, 8);
    $ct = substr($data, 16);
    return [$ct, $salt];
}

function encode($ct, $salt) {
    return base64_encode("Salted__" . $salt . $ct);
}

echo 'AES CBC 256 String encryption with passphrase' . PHP_EOL;

echo PHP_EOL . '# # # SECURITY WARNING: This code is provided for achieve    # # #' . PHP_EOL;
echo '# # # compatibility between different programming languages. # # #' . PHP_EOL;
echo '# # # It is not necessarily fully secure.                    # # #' . PHP_EOL;
echo '# # # Its security depends on the complexity and length      # # #' . PHP_EOL;
echo '# # # of the password, because of only one iteration and     # # #' . PHP_EOL;
echo '# # # the use of MD5.                                        # # #' . PHP_EOL;
echo '# # # DO NOT USE THIS CODE IN PRODUCTION                     # # #' . PHP_EOL;

$plaintext = 'The quick brown fox jumps over the lazy dog';
$passphrase = 'my secret passphrase';
echo PHP_EOL . 'passphrase: ' . $passphrase . PHP_EOL;

echo PHP_EOL . '* * * Encryption * * *' . PHP_EOL;
$ciphertextBase64 = aesCbcPassphraseEncryptToBase64($passphrase, $plaintext);
echo 'ciphertext (Base64): ' . $ciphertextBase64 . PHP_EOL;
echo 'output is (Base64) ciphertext' . PHP_EOL;

echo PHP_EOL . '* * * Decryption * * *' . PHP_EOL;
$decryptionPassphrase = $passphrase;
$ciphertextDecryptionBase64 = $ciphertextBase64;
echo 'decryptionPassphrase: ' . $decryptionPassphrase . PHP_EOL;
echo 'ciphertext (Base64): ' . $ciphertextDecryptionBase64 . PHP_EOL;
echo 'input is (Base64) ciphertext' . PHP_EOL;
$decryptedtext = aesCbcPassphraseDecryptFromBase64($decryptionPassphrase, $ciphertextDecryptionBase64);
echo 'plaintext: ' . $decryptedtext . PHP_EOL;
?>

Upvotes: 3

Related Questions