Rijndael加密报错‘BlockSize必须为128’的解决方案求助
解决Rijndael加密报错“BlockSize must be 128 in this implementation”的方案
问题根源
.NET平台下的Rijndael实现(包括RijndaelManaged)仅支持128位块大小,它本质是AES标准的实现(AES是Rijndael的子集,固定128位块大小)。代码中设置BlockSize = 256超出了实现支持范围,因此触发错误。
修改步骤及完整代码
以下是适配.NET实现的修改后代码,核心调整点:
- 将块大小改为128位
- 调整IV(初始化向量)长度为16字节(与128位块大小匹配)
- 修正加密后字节数组的拼接逻辑,以及解密时的拆分逻辑
internal static string Encrypt(string plainText, string passPhrase) { byte[] salt = GetSaltArray(); byte[] iv = GetIVArray(); byte[] plainBytes = Encoding.UTF8.GetBytes(plainText); using Rfc2898DeriveBytes keyDeriver = new Rfc2898DeriveBytes(passPhrase, salt, 1000); byte[] key = keyDeriver.GetBytes(32); // 256位密钥,Rijndael支持该长度 using RijndaelManaged rijndael = new RijndaelManaged(); rijndael.BlockSize = 128; // 修改为128位块大小 rijndael.Mode = CipherMode.CBC; rijndael.Padding = PaddingMode.PKCS7; using ICryptoTransform encryptor = rijndael.CreateEncryptor(key, iv); using MemoryStream ms = new MemoryStream(); using CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write); cs.Write(plainBytes, 0, plainBytes.Length); cs.FlushFinalBlock(); // 拼接顺序:salt(32字节) + iv(16字节) + 密文 byte[] encryptedData = salt.Concat(iv).Concat(ms.ToArray()).ToArray(); return Convert.ToBase64String(encryptedData); } internal static string Decrypt(string cipherText, string passPhrase) { byte[] encryptedBytes; try { encryptedBytes = Convert.FromBase64String(cipherText); } catch { return string.Empty; } // 拆分字节数组:前32字节是salt,接下来16字节是iv,剩余是密文 byte[] salt = encryptedBytes.Take(32).ToArray(); byte[] iv = encryptedBytes.Skip(32).Take(16).ToArray(); byte[] cipherBytes = encryptedBytes.Skip(48).ToArray(); using Rfc2898DeriveBytes keyDeriver = new Rfc2898DeriveBytes(passPhrase, salt, 1000); byte[] key = keyDeriver.GetBytes(32); using RijndaelManaged rijndael = new RijndaelManaged(); rijndael.BlockSize = 128; // 修改为128位块大小 rijndael.Mode = CipherMode.CBC; rijndael.Padding = PaddingMode.PKCS7; using ICryptoTransform decryptor = rijndael.CreateDecryptor(key, iv); using MemoryStream ms = new MemoryStream(cipherBytes); using CryptoStream cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read); byte[] plainBytes = new byte[cipherBytes.Length]; int readCount = cs.Read(plainBytes, 0, plainBytes.Length); return Encoding.UTF8.GetString(plainBytes, 0, readCount); } // 生成32字节的盐值 private static byte[] GetSaltArray() { byte[] salt = new byte[32]; using RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider(); rng.GetBytes(salt); return salt; } // 生成16字节的IV(匹配128位块大小) private static byte[] GetIVArray() { byte[] iv = new byte[16]; using RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider(); rng.GetBytes(iv); return iv; }
关键说明
- 块大小限制:.NET的Rijndael实现不支持256位块大小,必须固定为128位,这是平台实现的硬性限制,无法绕过。
- IV长度匹配:CBC模式下IV长度必须与块大小一致,因此从32字节改为16字节。
- 兼容性:修改后的代码保留了原有的密钥推导逻辑(Rfc2898DeriveBytes)和256位密钥,仅调整块大小和IV相关逻辑,尽可能保留原有加密逻辑的核心。
内容的提问来源于stack exchange,提问作者living_mantis
相关产品推荐
相关产品推荐

