C# .NET5环境下AES加密解密URL后丢失冒号字符问题求助
问题排查与修复方案
1 优先确认密文一致性
加密完成后输出的Base64字符串,和后续从文本文件读取到的待解密字符串必须完全一致:
- 读写文件时明确指定UTF8编码,示例代码如下:
// 写入 File.WriteAllText(文件路径, 密文字符串, Encoding.UTF8); // 读取 var 待解密字符串 = File.ReadAllText(文件路径, Encoding.UTF8);
避免系统默认编码差异导致密文字符被篡改。
- 检查是否有对Base64密文做额外的转义、过滤、序列化处理,部分框架会自动处理特殊字符导致密文损坏。
2 现有AES实现的缺陷修复
你当前的AES实现存在安全风险,同时可能触发.NET运行时的未定义行为:
- 禁止将IV和Key设置为相同值,CBC模式要求IV每次加密都必须是随机不可预测的,解密时IV需要和密文一起传递。
- 密钥生成逻辑不规范,直接截断用户输入的密钥会导致密钥熵不足,建议使用PBKDF2等标准密钥派生算法生成符合长度要求的密钥。
修复后的参考实现
using System.Security.Cryptography; using System.Text; private string EncryptString(string plainText, string password) { using Aes aes = Aes.Create(); // 生成随机16位IV aes.GenerateIV(); byte[] iv = aes.IV; // 使用PBKDF2派生128位密钥,salt可自行修改或和IV一起存储 byte[] key = Rfc2898DeriveBytes.Pbkdf2( password: password, salt: new byte[16], iterations: 100000, hashAlgorithm: HashAlgorithmName.SHA256, outputLength: 16 ); aes.Key = key; aes.Mode = CipherMode.CBC; aes.Padding = PaddingMode.PKCS7; using ICryptoTransform encryptor = aes.CreateEncryptor(); byte[] plainBytes = Encoding.UTF8.GetBytes(plainText); byte[] cipherBytes = encryptor.TransformFinalBlock(plainBytes, 0, plainBytes.Length); // 拼接IV和密文后转Base64,解密时先拆分前16位为IV byte[] resultBytes = new byte[iv.Length + cipherBytes.Length]; Buffer.BlockCopy(iv, 0, resultBytes, 0, iv.Length); Buffer.BlockCopy(cipherBytes, 0, resultBytes, iv.Length, cipherBytes.Length); return Convert.ToBase64String(resultBytes); } private string DecryptString(string cipherText, string password) { byte[] fullCipherBytes = Convert.FromBase64String(cipherText); // 拆分前16位为IV byte[] iv = fullCipherBytes.Take(16).ToArray(); byte[] cipherBytes = fullCipherBytes.Skip(16).ToArray(); using Aes aes = Aes.Create(); // 和加密用相同的参数派生密钥 byte[] key = Rfc2898DeriveBytes.Pbkdf2( password: password, salt: new byte[16], iterations: 100000, hashAlgorithm: HashAlgorithmName.SHA256, outputLength: 16 ); aes.Key = key; aes.IV = iv; aes.Mode = CipherMode.CBC; aes.Padding = PaddingMode.PKCS7; using ICryptoTransform decryptor = aes.CreateDecryptor(); byte[] plainBytes = decryptor.TransformFinalBlock(cipherBytes, 0, cipherBytes.Length); return Encoding.UTF8.GetString(plainBytes); }
3 仅冒号丢失的特殊场景排查
如果确认密文完全一致,修复AES实现后问题仍然存在,优先排查解密后的后续处理逻辑:
- 在解密方法
return前打断点,直接查看返回的字符串原始值,确认冒号是否存在。如果此处冒号正常,说明问题出在后续的字符串处理、UI展示逻辑,和加解密无关。 - 检查是否有误调用Url编码/解码、特殊字符过滤的逻辑,部分业务代码会默认清理非字母数字字符导致冒号被删除。
内容的提问来源于stack exchange,提问作者Joe_K
相关产品推荐
相关产品推荐

