PHP、OpenSSL与C#的AES加密互操作性问题求助
PHP AES-256-CBC加密结果的OpenSSL CLI与C#解密方案
现有一段固定不可修改的PHP脚本,通过openssl_encrypt实现AES-256-CBC加密。需要找到对应的OpenSSL CLI命令和C#代码,解密该脚本输出的加密字符串。目前尝试的OpenSSL命令无法得到匹配的加密/解密结果。
PHP加密脚本
<?php function bad_crypt($string, $action = 'e') { if (empty($string)) { return ""; } $encrypt_method = "AES-256-CBC"; $key = "3d13b07f244861f2d323d1734d773ce4bd079e2c17deb5695911e1387e0b579a"; $iv = "d9ec53dadaf1e968"; // bad practice, but this is just a test echo "key:"; echo "<br>"; echo $key; echo "<br>"; echo "iv:"; echo "<br>"; echo $iv; echo "<br>"; if ($action == 'e') { $output = base64_encode(openssl_encrypt($string, $encrypt_method, $key, 0, $iv)); } else if ($action == 'd') { $output = openssl_decrypt(base64_decode($string), $encrypt_method, $key, 0, $iv); } return $output; } $info = "mysecret"; $encInfo = bad_crypt($info); echo "encrypted:"; echo "<br>"; echo $encInfo; echo "<br>"; echo "<br>"; echo "<br>"; $t = bad_crypt($encInfo, "d"); echo "decrypted:"; echo "<br>"; echo $t; ?>
PHP脚本输出
key: 3d13b07f244861f2d323d1734d773ce4bd079e2c17deb5695911e1387e0b579a iv: d9ec53dadaf1e968 encrypted: QVBBaDcrdkRUdVFqZDV5cGFMNHJCdz09 key: 3d13b07f244861f2d323d1734d773ce4bd079e2c17deb5695911e1387e0b579a iv: d9ec53dadaf1e968 decrypted: mysecret
问题原因
之前尝试的OpenSSL命令(如下)无法匹配结果,核心原因是参数解析规则差异:
openssl.exe enc -e -aes-256-cbc -a -K 3d13b07f244861f2d323d1734d773ce4bd079e2c17deb5695911e1387e0b579a -iv d9ec53dadaf1e968 -in mysecret.txt
- PHP的
openssl_encrypt直接将密钥/IV的每个字符ASCII字节作为加密密钥/IV - OpenSSL CLI的
-K/-iv参数默认将传入字符串当作十六进制字节值解析,而非ASCII字节序列
需要将PHP中的密钥和IV字符串转换为对应ASCII字节的十六进制表示,再传入OpenSSL CLI。
解决方案
一、OpenSSL CLI 解密命令
先转换密钥和IV的ASCII字节为十六进制:
- 密钥ASCII字节十六进制:
33643133623037663234343836316632643332336431373334643737336365346264303739653263313764656235363935393131653133383765306235373961 - IV ASCII字节十六进制:
64396563353364616461663165393638
解密命令
echo "QVBBaDcrdkRUdVFqZDV5cGFMNHJCdz09" | openssl enc -d -aes-256-cbc -a -K 33643133623037663234343836316632643332336431373334643737336365346264303739653263313764656235363935393131653133383765306235373961 -iv 64396563353364616461663165393638
执行后输出:mysecret
加密验证命令(复现PHP结果)
echo -n "mysecret" | openssl enc -e -aes-256-cbc -a -K 33643133623037663234343836316632643332336431373334643737336365346264303739653263313764656235363935393131653133383765306235373961 -iv 64396563353364616461663165393638
执行后输出:QVBBaDcrdkRUdVFqZDV5cGFMNHJCdz09,与PHP输出一致。
二、C# 解密代码
C#中需将密钥和IV字符串转换为ASCII字节数组,使用Aes类完成解密:
using System; using System.IO; using System.Security.Cryptography; using System.Text; class Program { static void Main() { string encryptedBase64 = "QVBBaDcrdkRUdVFqZDV5cGFMNHJCdz09"; string key = "3d13b07f244861f2d323d1734d773ce4bd079e2c17deb5695911e1387e0b579a"; string iv = "d9ec53dadaf1e968"; byte[] keyBytes = Encoding.ASCII.GetBytes(key); byte[] ivBytes = Encoding.ASCII.GetBytes(iv); byte[] encryptedBytes = Convert.FromBase64String(encryptedBase64); string decryptedText; using (Aes aesAlg = Aes.Create()) { aesAlg.Key = keyBytes; aesAlg.IV = ivBytes; aesAlg.Mode = CipherMode.CBC; aesAlg.Padding = PaddingMode.PKCS7; // PHP默认使用PKCS7填充 ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV); using (MemoryStream msDecrypt = new MemoryStream(encryptedBytes)) { using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read)) { using (StreamReader srDecrypt = new StreamReader(csDecrypt)) { decryptedText = srDecrypt.ReadToEnd(); } } } } Console.WriteLine("解密结果:" + decryptedText); // 输出 mysecret } }
内容的提问来源于stack exchange,提问作者Quentin A. Miller
相关产品推荐
相关产品推荐

