如何将openssl加密解密转换成php

问题描述 投票:0回答:1

我正在尝试将以下 shell 命令转换为 php,但我没有得到正确的结果

$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;

以上适用于 php7.4。我尝试过以下方法

$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;

这不起作用。

key
由第 3 方提供

更新

我尝试过以下方法

创建密钥和 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

在cli上我可以使用密钥来加密和解密

加密

# 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=

解密

# 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]

在 PhP 中

我使用从 cli 创建的

key
iv
key
是提供给我的,我无法生成这个

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;
}

我尝试在 cli 上解码上述输出以检查其是否有效,但没有成功。我收到错误

bad magic number

输出

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

更新

我已经设法使解密工作,但加密不起作用

这就是我所拥有的

$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);
encryption openssl php-7.4
1个回答
3
投票

以下代码是一个完整的运行示例,使用 @Topaco 评论的“EVP_BytesToKey”密钥派生。

请注意,这种密钥派生是不安全,因为它使用损坏的MD5算法且迭代计数仅为1。请仅将代码用于迁移目的,谢谢。

这是一个可能的输出[因为存在随机元素,您的输出会有所不同]:

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

代码:

<?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;
?>
© www.soinside.com 2019 - 2024. All rights reserved.