C#与PHP使用AES-128-CBC加密数据结果不一致问题求助
问题原因及解决方案
核心问题1:密钥处理不匹配
PHP与C#对密钥的处理逻辑存在差异,这是最常见的不匹配原因:
- PHP的
md5()函数默认返回32字符长度的十六进制字符串(32字节),而AES-128要求密钥长度为16字节,openssl_encrypt会自动将传入的密钥截断为前16字节使用。 - 你当前C#代码中将MD5原始16字节哈希转成了32字符的十六进制字符串,再转UTF8得到32字节的密钥数组,此时如果设置
KeySize=128会因密钥长度不匹配报错,若你隐式改成了256位密钥则完全和PHP逻辑不一致。
额外注意:如果PHP端实际使用的是
md5('123456789', true)(返回16字节原始二进制哈希,这是加密场景下的常见写法,很多示例会漏写第二个参数),你C#中完全不需要将MD5哈希转成十六进制字符串,直接使用ComputeHash返回的16字节HashValue作为密钥即可。
核心问题2:明文编码引入额外字节
你使用StreamWriter写入明文,StreamWriter默认使用带BOM(字节顺序标记)的UTF8编码,会在明文开头额外写入3个字节的BOM标记,而PHP端的明文是无BOM的纯ASCII字符串,明文内容不一致自然加密结果不同。
核心问题3:加密参数未显式声明
Rijndael算法支持多种块大小和填充模式,你没有显式声明块大小和填充模式,不同.NET版本的默认值可能存在差异,和PHP端openssl_encrypt默认的PKCS7填充、128位块大小不匹配。
修正后的C#代码示例
string data = "data to be sent"; string base64data = Convert.ToBase64String(Encoding.UTF8.GetBytes(data)); // 处理密钥 MD5 hasher = MD5.Create(); byte[] hashValue = hasher.ComputeHash(Encoding.UTF8.GetBytes("123456789")); // 场景1:PHP端md5未加raw_output=true(返回32位十六进制字符串) string encryptionKeyHex = BitConverter.ToString(hashValue).Replace("-", "").ToLower(); byte[] fullKeyBytes = Encoding.ASCII.GetBytes(encryptionKeyHex); // 取前16字节作为AES-128密钥(和PHP截断逻辑一致) byte[] keyBytes = new byte[16]; Array.Copy(fullKeyBytes, keyBytes, 16); // 场景2:PHP端md5加了raw_output=true(返回16字节原始哈希,优先测试这个场景,更常用) // byte[] keyBytes = hashValue; byte[] iv = Encoding.ASCII.GetBytes("1234567891234567"); // 显式设置所有加密参数 using RijndaelManaged aes = new RijndaelManaged(); aes.Mode = CipherMode.CBC; aes.KeySize = 128; aes.BlockSize = 128; aes.Padding = PaddingMode.PKCS7; aes.Key = keyBytes; aes.IV = iv; // 直接处理字节流,避免StreamWriter的编码问题 byte[] plainBytes = new UTF8Encoding(false).GetBytes(base64data); using ICryptoTransform encryptor = aes.CreateEncryptor(); using MemoryStream msEncrypt = new MemoryStream(); using CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write); csEncrypt.Write(plainBytes, 0, plainBytes.Length); csEncrypt.FlushFinalBlock(); byte[] encryptedData = msEncrypt.ToArray(); Console.WriteLine($"Encrypted data: {Convert.ToBase64String(encryptedData)}");
内容的提问来源于stack exchange,提问作者V. Oikonomakos
相关产品推荐
相关产品推荐

