将密钥存入Web.Config后C# AES解密出现填充无效错误求助
问题背景
原本将AES加密密钥硬编码在代码中,改为从Web.Config的AppSettings读取后,解密函数抛出“Padding is invalid and cannot be removed”错误,相关解密代码如下:
public static string Decrypt(string cipherText) { string EncryptionKey = ConfigurationManager.AppSettings["EncryptionKey"].ToString(); string EncryptionCode = ConfigurationManager.AppSettings["EncryptionCode"].ToString(); byte[] key = Encoding.ASCII.GetBytes(EncryptionCode); cipherText = cipherText.Replace(" ", "+"); byte[] cipherBytes = Convert.FromBase64String(cipherText); using (Aes encryptor = Aes.Create()) { Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(EncryptionKey, key); encryptor.Key = pdb.GetBytes(32); encryptor.IV = pdb.GetBytes(16); using (MemoryStream ms = new MemoryStream()) { using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateDecryptor(), CryptoStreamMode.Write)) { cs.Write(cipherBytes, 0, cipherBytes.Length); cs.FlushFinalBlock(); cs.Close(); } cipherText = Encoding.Unicode.GetString(ms.ToArray()); } } return cipherText; }
可能的问题点及解决办法
Web.Config配置值不一致
硬编码时的EncryptionKey和EncryptionCode是固定字符串,存入配置文件时可能被误加空格、换行或特殊字符转义错误,导致读取的内容和原始硬编码值不符。
解决:直接把硬编码的原始值复制到Web.Config的对应配置项中,确保完全一致,无多余字符。编码方式不匹配
如果EncryptionCode包含非ASCII字符,用Encoding.ASCII.GetBytes转换时会丢失信息(ASCII不支持非ASCII字符,会替换为?),导致Rfc2898DeriveBytes生成的Key/IV和加密时不一致。
解决:确认EncryptionCode的字符集,若含非ASCII字符,改用Encoding.UTF8.GetBytes或Encoding.Unicode.GetBytes,且加密和解密保持相同编码方式。Rfc2898DeriveBytes迭代次数差异
.NET不同版本中Rfc2898DeriveBytes的默认迭代次数可能不同(比如早期.NET Framework默认1000,.NET Core+默认100000),如果加密时用了默认值,解密时默认值变化会导致密钥生成结果不同。
解决:显式指定迭代次数,保证加密解密一致,示例:Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(EncryptionKey, key, 1000);PaddingMode设置不一致
代码中注释了encryptor.Padding = PaddingMode.Zeros;,如果加密时设置了特定填充模式(比如Zeros),解密时用默认的PKCS7会导致填充验证失败。
解决:核对加密函数的PaddingMode设置,解密时保持完全一致,若加密用了Zeros则取消注释该行代码。Base64字符串恢复不完整
仅替换空格为+不足以处理所有URL安全的Base64编码(比如-替换为+、_替换为/),如果加密后的字符串经过URL编码存储,会导致Base64解析错误。
解决:补充完整的Base64恢复逻辑:cipherText = cipherText.Replace("-", "+").Replace("_", "/").Replace(" ", "+");密钥生成逻辑不一致
检查加密函数是否和当前解密逻辑一致:是否用相同的Rfc2898DeriveBytes参数,是否先取32字节作为Key、再取16字节作为IV。加密和解密的密钥生成逻辑必须完全匹配。
内容的提问来源于stack exchange,提问作者Aswini

