PHP转C#实现AES-256-CBC加密结果不匹配问题求助
问题原因
你的C#代码和PHP官方加密逻辑存在3处核心差异,导致输出结果不匹配:
- SHA256输出格式错误:PHP的
hash('sha256', $str)默认返回小写的十六进制字符串,而你的C#代码直接返回SHA256的原始二进制字节,导致后续生成的密钥、IV完全不符合要求。 - 密钥与IV生成逻辑错误:PHP是对SHA256返回的十六进制字符串做截断生成密钥和IV,你的C#代码是直接对原始二进制字节做截断,逻辑完全不一致。
- Base64编码次数不足:PHP的
openssl_encrypt在第四个参数为0时,默认返回已经做过一次base64编码的加密结果,原代码又对该结果做了第二次base64编码。而你的C#代码仅对加密后的原始二进制做了一次base64编码,少了一次编码步骤。
修复后的完整代码
using System; using System.IO; using System.Security.Cryptography; using System.Text; // 计算SHA256并返回小写十六进制字符串,和PHP默认hash输出一致 static string Sha256ToHex(string rawData) { using (SHA256 sha256 = SHA256.Create()) { byte[] hashBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(rawData)); StringBuilder sb = new StringBuilder(); foreach (byte b in hashBytes) { sb.Append(b.ToString("x2")); } return sb.ToString(); } } static string OpenSSLEncrypt(string plainText, string key) { string keyHashHex = Sha256ToHex(key); string ivHashHex = Sha256ToHex(key); // AES-256需要32字节密钥,取十六进制串前32个字符转UTF8字节 byte[] aesKey = Encoding.UTF8.GetBytes(keyHashHex.Substring(0, 32)); // AES需要16字节IV,取十六进制串前16个字符转UTF8字节 byte[] aesIv = Encoding.UTF8.GetBytes(ivHashHex.Substring(0, 16)); using (Aes aes = Aes.Create()) { aes.Key = aesKey; aes.IV = aesIv; aes.Mode = CipherMode.CBC; aes.Padding = PaddingMode.PKCS7; ICryptoTransform encryptor = aes.CreateEncryptor(); using (MemoryStream msEncrypt = new MemoryStream()) { using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write)) { byte[] plainBytes = Encoding.UTF8.GetBytes(plainText); csEncrypt.Write(plainBytes, 0, plainBytes.Length); csEncrypt.FlushFinalBlock(); } // 第一次base64,对应openssl_encrypt的默认返回值 string firstBase64 = Convert.ToBase64String(msEncrypt.ToArray()); // 第二次base64,对应PHP代码中的base64_encode操作 return Convert.ToBase64String(Encoding.UTF8.GetBytes(firstBase64)).Trim(); } } }
注意事项
传入的明文必须和测试用例的明文完全一致,包括空格、换行、引号格式,不要做任何格式化调整,否则加密结果会不匹配。
内容的提问来源于stack exchange,提问作者derodevil
相关产品推荐
相关产品推荐

