Asp.Net Core 3.1中使用AES解密文件特殊字符变为问号如何解决
问题根因
你遇到的乱码完全是编码使用错误导致的,加密阶段就已经丢失了特殊字符的信息,不是解密环节的单独问题:
- 你读取原始文件时用了UTF8编码拿到正确字符串后,转字节数组时错误使用了
ASCIIEncoding.ASCII:ASCII编码仅支持0-127范围内的字符,á、é这类拉丁特殊字符超出范围,转换时会直接被替换为?,加密时数据就已经损坏。 - 解密完成后将字节数组转回字符串时,你再次使用了
ASCIIEncoding.ASCII,二次破坏数据。 - 额外注意:你当前的代码仅支持处理纯文本格式的csv文件,绝对不能用来处理xlsx二进制文件:xlsx是压缩后的二进制格式,用
StreamReader按文本读取会直接破坏文件结构,需要直接读取原始字节流做加解密,不要做字符串转换。
修正后的加解密代码(仅适用于csv纯文本文件)
public static void Encrypt(IFormFile uploadFile) { ICryptoTransform transform = _crypt_provider.CreateEncryptor(); // 读取csv文本保持UTF8编码 string text; using (var reader = new StreamReader(uploadFile.OpenReadStream(), Encoding.UTF8)) { text = reader.ReadToEnd(); } // 改用UTF8转字节数组,保留所有特殊字符 byte[] originalBytes = Encoding.UTF8.GetBytes(text); byte[] encryptedBytes = transform.TransformFinalBlock(originalBytes, 0, originalBytes.Length); string textoEncrypted = Convert.ToBase64String(encryptedBytes); Debug.WriteLine($"El texto ingresado = {text} \nEl texto encriptado = {textoEncrypted}"); // 写入文件明确指定UTF8编码,避免系统默认编码差异 File.WriteAllText(uploadFile.FileName, textoEncrypted, Encoding.UTF8); } public static string Decrypt(IFormFile uploadFile) { // 读取加密后的base64文本明确指定UTF8编码 string text; using (var reader = new StreamReader(uploadFile.OpenReadStream(), Encoding.UTF8)) { text = reader.ReadToEnd(); } ICryptoTransform transform = _crypt_provider.CreateDecryptor(); byte[] encryptedBytes = Convert.FromBase64String(text); byte[] decryptedBytes = transform.TransformFinalBlock(encryptedBytes, 0, encryptedBytes.Length); // 改用UTF8转字符串,还原特殊字符 string textoDesencriptado = Encoding.UTF8.GetString(decryptedBytes); Debug.WriteLine($"El texto ingresado = {text} \nEl texto desencriptado = {textoDesencriptado}"); return textoDesencriptado; }
处理xlsx二进制文件的适配方案
不要做任何字符串转换,直接对字节流加解密即可:
// 加密xlsx示例 public static void EncryptBinaryFile(IFormFile uploadFile) { ICryptoTransform transform = _crypt_provider.CreateEncryptor(); // 直接读取所有原始字节 using var fileStream = uploadFile.OpenReadStream(); using var ms = new MemoryStream(); fileStream.CopyTo(ms); byte[] originalBytes = ms.ToArray(); byte[] encryptedBytes = transform.TransformFinalBlock(originalBytes, 0, originalBytes.Length); // 二进制加密结果直接写文件,如需base64存储可自行调整转换逻辑 File.WriteAllBytes(uploadFile.FileName, encryptedBytes); }
内容的提问来源于stack exchange,提问作者josem0
相关产品推荐
相关产品推荐

