当前位置: 首页 > 知识库问答 >
问题:

Openssl aes-256-cbc 从命令提示符加密和 PHP 解密(反之亦然)

胡泓
2023-03-14

我正在尝试通过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命令提示符下解密。所以请添加任何可能有帮助的建议。)

共有2个答案

拓拔嘉运
2023-03-14

正如@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
张建华
2023-03-14

OpenSSL语句在加密期间生成一个随机的8字节salt,它与密码一起使用OpenSSL函数EVP_BytesToKey()导出32字节密钥和16字节IV。

使用key和IV,在CBC模式下使用AES-256执行加密。结果包括Salted__的ASCII编码的串联,然后是盐和实际密文,所有Base64编码。

PHP/OpenSSL中的解密必须按如下方式实现:

  • 盐和实际密文的测定。
  • 使用盐、密码和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() 派生密钥现在被认为是不安全的。

 类似资料: