You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#实现AES+RSA加密通信时AES解密开头出现乱码如何解决

问题根因

最直接导致解密开头乱码的原因是服务端创建解密器的顺序错误:
你服务端代码先调用 aes.CreateDecryptor() 生成解密器,之后才给 aes.IV 赋值硬编码的固定值。CreateDecryptor() 方法会在调用时立即读取当前AES实例的Key和IV生成转换器,后续修改AES实例的IV不会对已经生成的解密器生效,导致解密器实际使用的是AES实例初始化时自动生成的随机IV,和加密时的IV不匹配,第一个加密块(通常16字节)解密错误,表现为开头乱码。

其他需要修复的错误

  • 所有NetworkStream.Read调用未处理返回值:TCP是流式协议,Read方法不保证一次性读取到你期望长度的所有数据,返回值代表本次实际读取到的字节数,你需要根据返回值截取有效字节,否则buffer中未填充的部分会被转为无效的\0字符,导致字符串分割、Base64解析出错。
  • 复用ICryptoTransform加密多段独立数据:AES默认CBC模式是链式加密,加密完一段数据调用TransformFinalBlock后,转换器状态可能不符合下一段独立数据的加密要求,每段独立数据加密/解密都应该重新创建对应转换器。
  • 密钥交换逻辑冗余混乱:你客户端生成RSA密钥对、发送公钥到服务端的逻辑完全无用,你需要的是客户端用服务端公钥加密AES密钥,服务端用自身私钥解密即可,当前服务端代码导入客户端公钥后又导入自身私钥,直接覆盖了之前的密钥配置,属于无效逻辑。
  • 硬编码IV存在安全风险:IV应该每次加密随机生成,随密文一起传输,硬编码IV会降低加密安全性。

修复示例

服务端核心逻辑调整(解决开头乱码的核心修改)

// 先赋值Key和IV,再创建解密器
aes.Key = rsa.Decrypt(Convert.FromBase64String(Encoding.UTF8.GetString(bytesFrom).Split("$")[0]), RSAEncryptionPadding.Pkcs1);
// 先设置IV
aes.IV = Encoding.UTF8.GetBytes("1234567890123456");
// 再创建解密器
ICryptoTransform decrypt = aes.CreateDecryptor();

通用Read方法封装(解决TCP流读取不完整问题)

private string ReadUntilDelimiter(NetworkStream stream, char delimiter = '$')
{
    var buffer = new List<byte>();
    int readByte;
    while ((readByte = stream.ReadByte()) != -1)
    {
        if ((char)readByte == delimiter) break;
        buffer.Add((byte)readByte);
    }
    return Encoding.UTF8.GetString(buffer.ToArray());
}

后续读取数据直接调用该方法即可拿到完整的、不包含分隔符的有效字符串,不需要手动处理分割和读取长度。

内容的提问来源于stack exchange,提问作者BurntRanch

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 22:06:04