使用C# AES-CBC解密Base64编码令牌提取声明时遇块不完整错误
解决AES解密报错“Input data is not a complete block”的问题
问题场景
对接第三方认证系统,对方发送Base64编码字符串,需先解码再解密获取用户声明。编写的C#解密方法测试时始终报错**“Input data is not a complete block”**,密钥为16字符,_jwtEncryptedToken为收到的Base64编码值。
原代码:
var key = Encoding.UTF8.GetBytes(_secretKey); byte[] iv; using (var aesAlg = Aes.Create()) { var decodedBytes = Convert.FromBase64String(_jwtEncryptedToken); iv = new byte[16]; Array.Copy(decodedBytes, 0, iv, 0, iv.Length); aesAlg.Key = key; aesAlg.IV = iv; aesAlg.Mode = CipherMode.CBC; aesAlg.Padding = PaddingMode.PKCS7; ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV); using (var msDecrypt = new MemoryStream(decodedBytes)) { using (var csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read)) { using (var srDecrypt = new StreamReader(csDecrypt)) { return srDecrypt.ReadToEnd(); } } } }
问题原因
你提取了前16字节作为IV,但解密时却把包含IV的整个字节流传给了解密器。AES CBC模式要求密文长度必须是块大小(16字节)的整数倍,IV被当成密文一部分后,实际密文长度减少了16字节,导致不符合块大小要求,触发报错。
修正方案
解密时跳过前16字节的IV,只处理后续的密文部分,修改后的代码如下:
var key = Encoding.UTF8.GetBytes(_secretKey); byte[] iv; using (var aesAlg = Aes.Create()) { var decodedBytes = Convert.FromBase64String(_jwtEncryptedToken); // 提取前16字节作为IV iv = new byte[16]; Array.Copy(decodedBytes, 0, iv, 0, iv.Length); aesAlg.Key = key; aesAlg.IV = iv; aesAlg.Mode = CipherMode.CBC; aesAlg.Padding = PaddingMode.PKCS7; ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV); // 跳过前16字节的IV,只处理后续的密文部分 using (var msDecrypt = new MemoryStream(decodedBytes, 16, decodedBytes.Length - 16)) { using (var csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read)) { using (var srDecrypt = new StreamReader(csDecrypt)) { return srDecrypt.ReadToEnd(); } } } }
关键修改点
- 使用
MemoryStream(byte[] buffer, int index, int count)重载构造方法,指定起始偏移量为16(跳过IV),长度为总字节数减去16,确保解密器只处理真正的密文。 - 需确认第三方加密逻辑与你的解密逻辑完全匹配:AES-128(16字节密钥)、CBC模式、PKCS7填充、IV放在密文头部。
额外检查项
- 确认Base64解码后的字节流总长度至少为32字节(16字节IV + 16字节最小密文块),若长度不足,说明接收的Base64字符串可能被截断或损坏。
内容的提问来源于stack exchange,提问作者Saif
相关产品推荐
相关产品推荐

