我正试图通过Windows命令提示符加密(openssl aes-256-cbc(一个字符串,并用PHP解密结果。
我已经通过进行了加密
echo {un:est@test.com,upass:klkKJS*dfd!j@d76w} | openssl enc -e -aes-256-cbc -a -salt -pass pass:sw8/M!CLl:=cmgtHts?v/Wb7C$Vk9Sy-{go.*+E;[GAg~KQi*rI!1#z;x/KT
对于解密,我的php代码是:
$ivlen = openssl_cipher_iv_length('aes-256-cbc');
$iv = openssl_random_pseudo_bytes($ivlen);
echo openssl_decrypt('U2FsdGVkX18ruQUgA9LEOOvdOUQXv/o8z6ZNO820MKzSIbMjFcyfNo1efQwAOINxMY9+UxZjxaT+JEWmlUyYQw==', 'aes-256-cbc', 'sw8/M!CLl:=cmgtHts?v/Wb7C$Vk9Sy-{go.*+E;[GAg~KQi*rI!1#z;x/KT', $options=0, $iv);
但解密后的字符串为空。请帮忙。
(注意:我还需要做相反的过程,即在php中加密和从WIN命令提示符中解密。因此,请添加任何可能有帮助的建议。(
OpenSSL语句在加密过程中生成一个随机的8字节salt,该salt与密码一起使用,通过OpenSSL函数EVP_BytesToKey()
导出一个32字节的密钥和一个16字节的IV。
使用密钥和IV,在CBC模式下使用AES-256进行加密。结果包括Salted__
的ASCII编码的级联,然后是salt和实际密文,所有密文都是Base64编码的。
PHP/OOpenSSL中的解密必须按照以下方式实现:
- 盐和实际密文的测定
- 使用salt、password和
EVP_BytesToKey()
获取密钥和IV - 使用密钥和IV在CBC模式下使用AES-256进行解密
一种可能的实现是:
<?php
function EVP_BytesToKey($salt, $password) {
$bytes = '';
$last = '';
while(strlen($bytes) < 48) {
$last = hash('md5', $last . $password . $salt, true);
$bytes.= $last;
}
return $bytes;
}
$saltCiphertext = base64_decode('U2FsdGVkX18ruQUgA9LEOOvdOUQXv/o8z6ZNO820MKzSIbMjFcyfNo1efQwAOINxMY9+UxZjxaT+JEWmlUyYQw==');
$salt = substr($saltCiphertext, 8, 8);
$ciphertext = substr($saltCiphertext, 16);
$keyIv = EVP_BytesToKey($salt, 'sw8/M!CLl:=cmgtHts?v/Wb7C$Vk9Sy-{go.*+E;[GAg~KQi*rI!1#z;x/KT');
$key = substr($keyIv, 0, 32);
$iv = substr($keyIv, 32);
echo openssl_decrypt($ciphertext, 'aes-256-cbc', $key, OPENSSL_RAW_DATA, $iv); // {un:est@test.com,upass:klkKJS*dfd!j@d76w}
?>
在早期版本中,OpenSSL默认使用MD5作为EVP_BytesToKey()
中的摘要,版本为V1.1.0 SHA256。在发布的示例中,MD5解密是成功的,因此显然MD5被用于加密
请注意,使用EVP_BytesToKey()
的密钥派生现在被认为是不安全的。
正如@Topaco建议对通过命令提示符编码的字符串进行PHP openssl解密,这里有一个相反的例子(在命令行中进行PHP加密解码(。感谢@Topaco的评论和这段代码。
<?php
function EVP_BytesToKey($salt, $password) {
$bytes = '';
$last = '';
while(strlen($bytes) < 48) {
$last = hash('md5', $last . $password . $salt, true);
$bytes.= $last;
}
return $bytes;
}
$saltDeciphertext= '{un:est@test.com,upass:klkKJS*dfd!j@d76w}';
$crypttext = "Salted__";
$salt= random_bytes(8);
$crypttext .= $salt;
$keyIV= EVP_BytesToKey($salt, 'sw8/M!CLl:=cmgtHts?v/Wb7C$Vk9Sy-{go.*+E;[GAg~KQi*rI!1#z;x/KT');
$key = substr($keyIV, 0, 32);
$iv = substr($keyIV, 32);
$crypttext .= openssl_encrypt($saltDeciphertext, 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv);
echo base64_encode($crypttext);
?>
后续解密命令:
echo U2FsdGVkX1+rDCycmwvc6rImKmrzaC9WTlzFanXt476975aYQcxPt2fgnRazm7CorGkpAWm9vmcu33YpiTYziw== | openssl enc -d -aes-256-cbc -a -salt -pass pass:sw8/M!CLl:=cmgtHts?v/Wb7C$Vk9Sy-{go.*+E;[GAg~KQi*rI!1#z;x/KT