Я написал небольшой класс для симметричного шифрования с помощью openssl и шифрует и расшифровывает его в PHP, но я не могу либо расшифровать вывод с помощью командной строки, либо зашифровать одни и те же данные таким же образом.
Мой класс:
Class SimpleCrypt { public static function encrypt($password, $data, $enc_method='AES-256-CBC', $hash_method='SHA512') { self::check_methods($enc_method, $hash_method); $iv = self::hashIV($password, $hash_method, openssl_cipher_iv_length($enc_method)); $infostr = sprintf('$%s$%s$', $enc_method, $hash_method); return $infostr . openssl_encrypt($data, $enc_method, $password, false, $iv); } public static function decrypt($password, $edata) { $e_arr = explode('$', $edata); if( count($e_arr) != 4 ) { Throw new Exception('Given data is missing crucial sections.'); } $enc_method = $e_arr[1]; $hash_method = $e_arr[2]; self::check_methods($enc_method, $hash_method); $iv = self::hashIV($password, $hash_method, openssl_cipher_iv_length($enc_method)); return openssl_decrypt($e_arr[3], $enc_method, $password, false, $iv); } private static function hashIV($password, $method, $iv_size) { $myhash = hash($method, $password, TRUE); while( strlen($myhash) < $iv_size ) { $myhash .= hash($method, $myhash, TRUE); } return substr($myhash, 0, $iv_size); } private static function check_methods($enc, $hash) { if( ! function_exists('openssl_encrypt') ) { Throw new Exception('openssl_encrypt() not supported.'); } else if( ! in_array($enc, openssl_get_cipher_methods()) ) { Throw new Exception('Encryption method ' . $enc . ' not supported.'); } else if( ! in_array(strtolower($hash), hash_algos()) ) { Throw new Exception('Hashing method ' . $hash . ' not supported.'); } } } // -- end class SimpleCrypt -- // $enc = SimpleCrypt::encrypt('pass', 'test data'); $dec = SimpleCrypt::decrypt('pass', $enc); echo $enc . "\n" . $dec; // Output: // $AES-256-CBC$SHA512$yH0uN95Vya0pTwcoJRFb+g== // test data
Этот бит кода воспроизводит IV:
php -r 'echo strtoupper(bin2hex(substr(hash("SHA512", "pass", true), 0, openssl_cipher_iv_length("AES-256-CBC"))));' //output: 5B722B307FCE6C944905D132691D5E4A
Но этот код дает мне искаженный оттуп, который не похож на вход:
$ echo yH0uN95Vya0pTwcoJRFb+g== | base64 -d | openssl enc -AES-256-CBC -d -nosalt -nopad -k pass -iv 5B722B307FCE6C944905D132691D5E4A ã`ÈAgè}½5øÍÝEÞ 00000000 e3 60 c8 41 67 e8 7d bd 35 00 f8 cd dd 45 13 de |.`.Ag.}.5....E..|
Кодирование данных из командной строки дает мне:
$ echo "test data" | openssl enc -e -AES-256-CBC -nosalt -k pass -iv 5B722B307FCE6C944905D132691D5E4A | hexdump -C 00000000 ca fc 84 6a 95 51 8f 0e 61 14 96 77 4e 22 dd 39 |...jQ.a..wN".9| $ echo "test data" | openssl enc -e -AES-256-CBC -nosalt -k pass -iv 5B722B307FCE6C944905D132691D5E4A | base64 yvyEapVRjw5hFJZ3TiLdOQ==
Может ли кто-нибудь сказать мне, что я сделал неправильно в своем PHP-коде?
Чтобы переформулировать решение из ответа Даниэля, нам нужно использовать аргумент -K
для openssl, а не -k
или -pass
и он ожидает шестнадцатеричное представление строки. например:
echo strtoupper(bin2hex('pass')); //output: 70617373
И тогда правильная команда:
echo yH0uN95Vya0pTwcoJRFb+g== | base64 -d | openssl enc -AES-256-CBC -d -nosalt -K 70617373 -iv 5B722B307FCE6C944905D132691D5E4A | hexdump -C 00000000 74 65 73 74 20 64 61 74 61 |test data|
openssl_encrypt()
названный аргумент password
для PHP openssl_encrypt()
не является паролем, это фактический ключ. При использовании командной строки openssl enc
с нижним регистром -k
, OpenSSL выведет ключ из пароля с помощью функции деривации ключа. Вы хотите использовать openssl enc
с верхним регистром -K
и шестнадцатеричным представлением ключа; и убедитесь, что openssl_encrypt()
достаточно длинный ключ в аргументе password
.
См. Также самую первую заметку, внесенную пользователями в руководстве PHP по openssl_encrypt () .