RijndaelManaged CreateDecryptor解密报待解密数据长度无效异常
问题根因
你的FromHex方法逻辑没有问题,异常和字节数组生成无关,核心原因有两个:
- 算法块长度要求不匹配,且密文不兼容
你之前使用的TripleDESCryptoServiceProvider块大小固定为64位(8字节),测试用的密文字符串C9B7163BFA3E5E46转成字节数组刚好是8字节,满足TripleDES的块长度要求,且本身就是TripleDES加密生成的,所以之前运行正常。
而RijndaelManaged默认块大小为128位(16字节),要求待解密数据长度必须是块大小的整数倍,你传入的密文仅8字节,达不到最小块长度要求,且密文本身是TripleDES算法的输出,和Rijndael算法完全不兼容,自然会抛出长度无效的异常。 - 解密方法存在逻辑bug
你当前的Decrypt方法中,读取流时写死了读取长度为encryptedData.Length - 1,主动少读1字节,就算密文长度匹配,也会出现解密数据截断,甚至触发填充校验异常。
修复步骤
- 不要跨算法解密密文:不同对称加密算法的输出完全不通用,你不能把TripleDES生成的密文直接传给Rijndael解密器处理。如果要切换到Rijndael(AES标准的原型算法,安全性远高于TripleDES),必须使用配置完全一致的Rijndael加密器重新生成密文,保证密文长度是对应块大小的整数倍。
- 显式配置所有算法参数,不要依赖默认值:初始化加密提供程序时,必须显式指定和加密端完全一致的密钥、IV、块大小、加密模式、填充模式,避免环境或版本差异导致默认配置漂移:
case MyProject.Framework.Security.Symmetric.Provider.Rijndael: this._crypto = new RijndaelManaged { Key = key, // 密钥长度支持16/24/32字节,必须和加密端完全一致 IV = iv, // 128位块大小对应IV长度为16字节,必须和加密端完全一致 BlockSize = 128, Mode = CipherMode.CBC, Padding = PaddingMode.PKCS7 }; break;
- 修正解密流的读取逻辑:不要手动计算读取长度,直接用流拷贝逻辑完整读取解密后的数据,避免截断问题:
public byte[] Decrypt(byte[] encryptedData) { using var stream = new MemoryStream(encryptedData); using var cryptoStream = new CryptoStream(stream, this._crypto.CreateDecryptor(), CryptoStreamMode.Read); using var resultStream = new MemoryStream(); cryptoStream.CopyTo(resultStream); return resultStream.ToArray(); }
存量数据迁移提示
如果你的系统里已经存了大量TripleDES加密的历史数据,不能直接全局切换成Rijndael解密。需要先保留TripleDES的解密逻辑处理旧数据,新产生的数据全部用Rijndael加密存储,后台逐步把旧数据解密后用Rijndael重加密,完成平滑迁移,避免历史数据无法解密。
内容的提问来源于stack exchange,提问作者RaZzLe
相关产品推荐
相关产品推荐

