C# AESManaged加密正常,解密图片抛异常但仅右下角有冗余
问题分析与解决方案
问题概述
客户端通过UDP发送AES加密后的图像数据,服务器拼接后解密时抛出异常,但忽略异常后保存的图像仅右下角有冗余数据,其余部分正常。非加密图像传输完全正常,且将服务器的解密代码放到客户端执行时解密完全正常。
关键背景
- 测试阶段使用静态Key/IV,随机Key/IV下其他类型消息加解密100%正常;
- 流程为:加密完整字节数组→拆分发送→服务器拼接→解密;
- 解密用Read模式抛异常,用Write模式则所有消息解密失败。
可能原因与解决办法
1. UDP数据包丢失或拼接错误
UDP是无连接协议,虽然非加密传输正常,但加密数据对完整性要求极高——哪怕丢失1个字节,解密到最后校验PKCS7 padding时就会抛出异常。
- 验证方式:客户端加密后计算字节数组的MD5哈希值,服务器拼接完
wholeImage后也计算MD5,对比两者是否一致;同时检查客户端发送的分片数量与服务器接收的imgParts数组长度是否匹配。 - 修复点:
- 确认客户端拆分逻辑中的
1224与Message.MaxMessageSize一致,避免最后一段数据拆分错误; - UDP传输时增加分片序号、校验和机制,确保所有分片按序接收,无丢失或重复。
- 确认客户端拆分逻辑中的
2. 解密流程未正确处理Padding
原服务器解密代码仅通过cs.Read读取数据,未让CryptoStream完整处理PKCS7 padding的校验与去除,导致数据完整时也可能因流程不完整触发异常。
修改解密代码如下,确保CryptoStream完成整个解密流程:
public static byte[] Decrypt(ushort fromClientId, byte[] cipherText, byte[] iv) { try { using (AesManaged aes = new AesManaged()) { aes.Mode = CipherMode.CBC; aes.Padding = PaddingMode.PKCS7; aes.Key = new byte[16]; // 实际使用替换为真实Key aes.IV = new byte[16]; // 实际使用替换为客户端传来的iv ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key, aes.IV); using (MemoryStream ms = new MemoryStream(cipherText)) using (CryptoStream cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read)) using (MemoryStream resultMs = new MemoryStream()) { cs.CopyTo(resultMs); // 完整读取解密流,自动处理padding校验与去除 return resultMs.ToArray(); } } } catch (Exception e) { Debug.LogError("Decrypt Error: " + e.Message + "\n" + e.StackTrace); return null; } }
3. 客户端加密未完成Padding写入
客户端加密代码中,CryptoStream虽会在using块结束时自动处理,但显式调用FlushFinalBlock()可确保PKCS7 padding被正确写入加密流:
using (CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write)) { cs.Write(plainText, 0, plainText.Length); cs.FlushFinalBlock(); // 显式完成加密,确保padding写入 }
验证步骤
- 先校验客户端加密后与服务器拼接后的字节数组MD5,确认数据传输完整性;
- 替换解密代码后重新测试,若仍抛异常则确定问题出在UDP传输环节;
- 检查UDP分片的序号与长度,确保所有分片被正确接收拼接。
内容的提问来源于stack exchange,提问作者MikeyMike
相关产品推荐
相关产品推荐

