如何将openssl加解密shell命令转换为PHP原生实现
解决方案:openssl enc加密命令转原生PHP实现
核心错误原因
openssl enc -k传入的是密码短语而非直接AES密钥,openssl默认通过EVP_BytesToKey算法结合随机盐、指定的MD5哈希派生实际使用的AES密钥和IV,不会直接用传入字符串作为密钥- 你之前的代码返回了
md5($ciphertext_raw),返回值是密文的哈希结果而非密文本身,自然无法解密 - openssl默认输出的加密结果固定以
Salted__字符串为前缀,拼接8字节随机盐后再拼接密文,你之前的输出不符合该格式,所以解密时会报bad magic number错误 - 直接传入十六进制格式的密钥时没有转成二进制,密钥长度不符合AES-256要求的32字节标准
完整可运行实现
function opensslEncryptAES256CBC(string $plaintext, string $passphrase): ?string { // 完全对齐openssl默认的EVP_BytesToKey MD5派生逻辑 function evpBytesToKey(string $salt, string $passphrase, int $keyLen = 32, int $ivLen = 16): string { $data = ''; $result = ''; while (strlen($result) < $keyLen + $ivLen) { $data = md5($data . $passphrase . $salt, true); $result .= $data; } return $result; } // openssl默认生成8字节随机盐 $salt = openssl_random_pseudo_bytes(8); $keyIv = evpBytesToKey($salt, $passphrase); $key = substr($keyIv, 0, 32); // AES-256要求密钥长度为32字节 $iv = substr($keyIv, 32, 16); // CBC模式要求IV长度为16字节 // 加密得到二进制原始密文 $ciphertextRaw = openssl_encrypt( $plaintext, 'aes-256-cbc', $key, OPENSSL_RAW_DATA, $iv ); if ($ciphertextRaw === false) { return null; } // 按openssl默认格式拼接后base64编码,和原shell命令输出完全兼容 return base64_encode('Salted__' . $salt . $ciphertextRaw); }
验证方法
// 测试示例 $passphrase = 'my_key'; $plaintext = 'email@gmail.com'; $encrypted = opensslEncryptAES256CBC($plaintext, $passphrase); echo $encrypted . PHP_EOL; // 命令行验证解密:echo 输出的加密字符串 | openssl enc -d -aes-256-cbc -a -k my_key -md md5
兼容说明
如果需要使用固定盐/IV测试,把openssl_random_pseudo_bytes(8)替换为对应盐的二进制值即可;如果是直接使用预生成的十六进制密钥,调用前用hex2bin()将十六进制密钥转成32字节二进制值再传入加密函数即可。
内容的提问来源于stack exchange,提问作者shorif2000
相关产品推荐
相关产品推荐

