AES解密结果异常:部分字符丢失问题求助
AES解密后字符丢失问题修复
问题重现
使用AES加密字符串"5&&64&&41&&false&&&&dc&&"后解密,结果仅得到"5&&64&&41&&false",末尾的"&&&&dc&&"丢失。原代码如下:
public class Program { static void Main(string[] args) { Program program = new Program(); var toEncryptReturn = program.EncryptString("5&&64&&41&&false&&&&dc&&", "mysmallkey123456"); var toDecryptReturn = program.DecryptString(toEncryptReturn, "mysmallkey123456"); } public string EncryptString(string text, string keyString) { var key = Encoding.UTF8.GetBytes(keyString); using (var aesAlg = Aes.Create()) { using (var encryptor = aesAlg.CreateEncryptor(key, aesAlg.IV)) { aesAlg.Padding = PaddingMode.None; using (var msEncrypt = new MemoryStream()) { using (var csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write)) using (var swEncrypt = new StreamWriter(csEncrypt)) { swEncrypt.Write(text); } var iv = aesAlg.IV; var decryptedContent = msEncrypt.ToArray(); var result = new byte[iv.Length + decryptedContent.Length]; Buffer.BlockCopy(iv, 0, result, 0, iv.Length); Buffer.BlockCopy(decryptedContent, 0, result, iv.Length, decryptedContent.Length); return Convert.ToBase64String(result); } } } } public string DecryptString(string cipherText, string keyString) { var fullCipher = Convert.FromBase64String(cipherText); var iv = new byte[16]; var cipher = new byte[16]; Buffer.BlockCopy(fullCipher, 0, iv, 0, iv.Length); Buffer.BlockCopy(fullCipher, iv.Length, cipher, 0, iv.Length); var key = Encoding.UTF8.GetBytes(keyString); using (var aesAlg = Aes.Create()) { aesAlg.Padding = PaddingMode.None; using (var decryptor = aesAlg.CreateDecryptor(key, iv)) { string result; using (var msDecrypt = new MemoryStream(cipher)) { using (var csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read)) { using (var srDecrypt = new StreamReader(csDecrypt)) { result = srDecrypt.ReadToEnd(); } } } return result; } } } }
错误原因
PaddingMode.None导致数据截断:
AES是块加密算法,固定块大小为16字节。当设置PaddingMode.None时,加密数据的字节长度必须是16的整数倍,否则超出部分会被丢弃。原字符串转UTF8字节后长度为24,不是16的倍数,因此加密时仅处理了前16字节对应的字符,剩余8字节内容被截断。解密时硬编码密文长度:
解密代码中直接将密文长度固定为16字节,忽略了实际加密后的数据长度,导致仅解密了前16字节的内容。AES参数设置顺序错误:
在创建Encryptor之后才设置PaddingMode.None,此时加密器已使用默认的Padding配置初始化,设置不生效。
修复方案
- 使用默认的
PaddingMode.PKCS7(或按需选择合适的填充模式),自动处理块大小对齐问题,避免手动截断。 - 先配置AES的Key、IV、Padding等参数,再创建加密/解密器。
- 解密时根据实际密文长度提取数据,不硬编码长度。
- 确保加密完成后CryptoStream完成所有写入操作(using语句可自动处理,但需保证流正确关闭)。
修正后的代码
public class Program { static void Main(string[] args) { Program program = new Program(); var encrypted = program.EncryptString("5&&64&&41&&false&&&&dc&&", "mysmallkey123456"); var decrypted = program.DecryptString(encrypted, "mysmallkey123456"); // 输出:5&&64&&41&&false&&&&dc&& Console.WriteLine(decrypted); } public string EncryptString(string text, string keyString) { var key = Encoding.UTF8.GetBytes(keyString); // AES密钥长度必须是16、24或32字节,这里keyString是16字节,符合要求 if (key.Length != 16 && key.Length != 24 && key.Length != 32) { throw new ArgumentException("密钥长度必须为16、24或32字节"); } using (var aesAlg = Aes.Create()) { aesAlg.Key = key; aesAlg.GenerateIV(); // 自动生成随机IV aesAlg.Padding = PaddingMode.PKCS7; // 使用PKCS7填充 using (var encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV)) using (var msEncrypt = new MemoryStream()) { // 先写入IV到结果,方便解密时使用 msEncrypt.Write(aesAlg.IV, 0, aesAlg.IV.Length); using (var csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write)) using (var swEncrypt = new StreamWriter(csEncrypt)) { swEncrypt.Write(text); } return Convert.ToBase64String(msEncrypt.ToArray()); } } } public string DecryptString(string cipherText, string keyString) { var fullCipher = Convert.FromBase64String(cipherText); var key = Encoding.UTF8.GetBytes(keyString); if (key.Length != 16 && key.Length != 24 && key.Length != 32) { throw new ArgumentException("密钥长度必须为16、24或32字节"); } // 提取IV(前16字节) var iv = new byte[16]; Buffer.BlockCopy(fullCipher, 0, iv, 0, iv.Length); // 提取实际密文(IV之后的所有字节) var cipher = new byte[fullCipher.Length - iv.Length]; Buffer.BlockCopy(fullCipher, iv.Length, cipher, 0, cipher.Length); using (var aesAlg = Aes.Create()) { aesAlg.Key = key; aesAlg.IV = iv; aesAlg.Padding = PaddingMode.PKCS7; using (var decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV)) using (var msDecrypt = new MemoryStream(cipher)) using (var csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read)) using (var srDecrypt = new StreamReader(csDecrypt)) { return srDecrypt.ReadToEnd(); } } } }
内容的提问来源于stack exchange,提问作者subhrendu
相关产品推荐
相关产品推荐

