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

AES解密偶发“Padding is invalid and cannot be removed”错误排查求助

加密解密偶发Padding无效错误的排查与修复

问题现象

网站A执行加密、网站B执行解密,多数场景正常,但偶尔抛出错误:System.Security.Cryptography.CryptographicException: Padding is invalid and cannot be removed,错误触发在解密代码的cStream.Close()行,两端均配置了PKCS7填充模式。

原加密解密代码

Public Shared Function Encrypt(ByVal inText As String) As String
        Dim bytesBuff As Byte() = Encoding.Unicode.GetBytes(inText)
        Dim mKey As String = System.Configuration.ConfigurationManager.AppSettings("EncodeDecodeKey")
        Using aes__1 As Aes = Aes.Create()
            Dim crypto As New Rfc2898DeriveBytes(mKey, New Byte() {&H49, &H76, &H61, &H6E, &H20, &H4D, &H65, &H64, &H76, &H65, &H64, &H65, &H76})
            aes__1.Key = crypto.GetBytes(32)
            aes__1.IV = crypto.GetBytes(16)
            aes__1.Padding = PaddingMode.PKCS7  
            Using mStream As New MemoryStream()
                Using cStream As New CryptoStream(mStream, aes__1.CreateEncryptor(), CryptoStreamMode.Write)
                    cStream.Write(bytesBuff, 0, bytesBuff.Length)
                    cStream.Close()
                End Using
                inText = Convert.ToBase64String(mStream.ToArray())
            End Using
        End Using

        'encode for use with query string
        Return HttpUtility.UrlEncode(inText)
    End Function

 Public Shared Function Decrypt(ByVal cryptTxt As String) As String
        Dim mKey As String = System.Configuration.ConfigurationManager.AppSettings("EncodeDecodeKey")
        cryptTxt = cryptTxt.Replace(" ", "+")
        cryptTxt = cryptTxt.Replace("-", "+")
        cryptTxt = cryptTxt.Replace("_", "/")
        cryptTxt = HttpUtility.HtmlDecode(cryptTxt)
        Dim bytesBuff As Byte() = Convert.FromBase64String(cryptTxt)
        Using aes__1 As Aes = Aes.Create()
            Dim crypto As New Rfc2898DeriveBytes(mKey, New Byte() {&H49, &H76, &H61, &H6E, &H20, &H4D, &H65, &H64, &H76, &H65, &H64, &H65, &H76})
            aes__1.Key = crypto.GetBytes(32)
            aes__1.IV = crypto.GetBytes(16)
            aes__1.Padding = PaddingMode.PKCS7  
            Using mStream As New MemoryStream()
                Using cStream As New CryptoStream(mStream, aes__1.CreateDecryptor(), CryptoStreamMode.Write)
                    cStream.Write(bytesBuff, 0, bytesBuff.Length)
                    cStream.Close()
                End Using
                cryptTxt = Encoding.Unicode.GetString(mStream.ToArray())
            End Using
        End Using
        Return cryptTxt
    End Function

核心问题分析与修复方案

1. URL编码/解码逻辑错误

加密后用HttpUtility.UrlEncode处理字符串,但解密时先做字符替换再调用HtmlDecode,这会导致UrlEncode后的%2B(对应Base64的+)无法被还原,进而引发Base64解码错误,最终导致填充验证失败。

修复:先调用HttpUtility.UrlDecode还原Url编码的字符串,再处理可能的Base64兼容替换:

' 解密函数中替换原字符串处理逻辑
cryptTxt = HttpUtility.UrlDecode(cryptTxt)
cryptTxt = cryptTxt.Replace(" ", "+").Replace("-", "+").Replace("_", "/")

2. CryptoStream未显式处理最终块

虽然Close()会隐式调用FlushFinalBlock(),但显式调用能确保所有加密/解密数据(包括PKCS7填充数据)被完整处理,避免异常场景下的数据截断。

修复:在加密和解密的cStream.Close()前添加cStream.FlushFinalBlock():

' 加密函数中
cStream.Write(bytesBuff, 0, bytesBuff.Length)
cStream.FlushFinalBlock()
cStream.Close()

' 解密函数中
cStream.Write(bytesBuff, 0, bytesBuff.Length)
cStream.FlushFinalBlock()
cStream.Close()

3. 密钥一致性验证

确认网站A和网站B的EncodeDecodeKey配置完全一致(包括大小写、特殊字符),Rfc2898DeriveBytes会基于密钥和盐生成Key/IV,密钥不一致会直接导致解密时填充验证失败。

4. 传输过程中的字符串完整性校验

偶发错误可能源于传输时的字符串截断或篡改(如URL参数过长被截断、中间代理修改),可在加密后对生成的字符串添加哈希校验(如SHA256),解密前先校验哈希确保数据未被修改。

修正后的完整代码示例

加密函数

Public Shared Function Encrypt(ByVal inText As String) As String
    Dim bytesBuff As Byte() = Encoding.Unicode.GetBytes(inText)
    Dim mKey As String = System.Configuration.ConfigurationManager.AppSettings("EncodeDecodeKey")
    Using aes__1 As Aes = Aes.Create()
        Dim crypto As New Rfc2898DeriveBytes(mKey, New Byte() {&H49, &H76, &H61, &H6E, &H20, &H4D, &H65, &H64, &H76, &H65, &H64, &H65, &H76})
        aes__1.Key = crypto.GetBytes(32)
        aes__1.IV = crypto.GetBytes(16)
        aes__1.Padding = PaddingMode.PKCS7  
        Using mStream As New MemoryStream()
            Using cStream As New CryptoStream(mStream, aes__1.CreateEncryptor(), CryptoStreamMode.Write)
                cStream.Write(bytesBuff, 0, bytesBuff.Length)
                cStream.FlushFinalBlock()
                cStream.Close()
            End Using
            inText = Convert.ToBase64String(mStream.ToArray())
        End Using
    End Using

    Return HttpUtility.UrlEncode(inText)
End Function

解密函数

Public Shared Function Decrypt(ByVal cryptTxt As String) As String
    Dim mKey As String = System.Configuration.ConfigurationManager.AppSettings("EncodeDecodeKey")
    cryptTxt = HttpUtility.UrlDecode(cryptTxt)
    cryptTxt = cryptTxt.Replace(" ", "+").Replace("-", "+").Replace("_", "/")
    
    Dim bytesBuff As Byte() = Convert.FromBase64String(cryptTxt)
    Using aes__1 As Aes = Aes.Create()
        Dim crypto As New Rfc2898DeriveBytes(mKey, New Byte() {&H49, &H76, &H61, &H6E, &H20, &H4D, &H65, &H64, &H76, &H65, &H64, &H65, &H76})
        aes__1.Key = crypto.GetBytes(32)
        aes__1.IV = crypto.GetBytes(16)
        aes__1.Padding = PaddingMode.PKCS7  
        Using mStream As New MemoryStream()
            Using cStream As New CryptoStream(mStream, aes__1.CreateDecryptor(), CryptoStreamMode.Write)
                cStream.Write(bytesBuff, 0, bytesBuff.Length)
                cStream.FlushFinalBlock()
                cStream.Close()
            End Using
            cryptTxt = Encoding.Unicode.GetString(mStream.ToArray())
        End Using
    End Using
    Return cryptTxt
End Function

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 14:24:19