C# AES解密希伯来字母显示为问号问题求助
解决希伯来字母加密解密后显示为问号的问题
这个问题的核心原因非常明确:你使用的ASCIIEncoding根本不支持希伯来字母这类非ASCII字符!ASCII编码仅覆盖0-127的基础字符,任何超出这个范围的字符(包括希伯来语、中文、阿拉伯语等)都会被直接替换成问号?,所以从加密前的字节转换阶段就已经丢失了原始字符信息,解密自然只能得到一堆问号。
下面是具体的修复方案和优化后的代码:
1. 替换编码为UTF-8(或Unicode)
UTF-8是通用的Unicode字符编码,完美支持希伯来字母,而且兼容性好。你需要把所有ASCIIEncoding替换为UTF8Encoding,并且加密和解密必须使用完全相同的编码。
2. 完善AES加密的必要配置
你的原始代码缺少了AES加密的关键参数:初始化向量(IV)、加密模式和填充模式。这些参数在加密和解密时必须完全一致,否则解密会失败或乱码。另外,IV应该是随机生成的(不要硬编码),每次加密生成新的IV,然后和密文一起存储/传输。
优化后的完整代码示例
using System; using System.IO; using System.Security.Cryptography; using System.Text; public class AesEncryptionHelper { // 注意:密钥需要是256位(32字节),这里只是示例,请使用安全的密钥管理方式 private static readonly byte[] _key = Encoding.UTF8.GetBytes("Your32ByteLongSecureKeyHere123"); public static string Encrypt(string plainText) { if (string.IsNullOrEmpty(plainText)) throw new ArgumentNullException(nameof(plainText)); using (AesCryptoServiceProvider aes = new AesCryptoServiceProvider()) { aes.BlockSize = 128; aes.KeySize = 256; aes.Key = _key; aes.Mode = CipherMode.CBC; // 推荐使用CBC模式 aes.Padding = PaddingMode.PKCS7; // 标准填充模式 // 生成随机IV aes.GenerateIV(); byte[] iv = aes.IV; // 创建加密器 ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, iv); // 转换明文为UTF-8字节 byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText); // 执行加密 byte[] cipherTextBytes; using (MemoryStream ms = new MemoryStream()) { using (CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write)) { cs.Write(plainTextBytes, 0, plainTextBytes.Length); cs.FlushFinalBlock(); cipherTextBytes = ms.ToArray(); } } // 将IV和密文拼接(IV在前,方便解密时拆分),然后转为Base64字符串返回 byte[] combinedBytes = new byte[iv.Length + cipherTextBytes.Length]; Buffer.BlockCopy(iv, 0, combinedBytes, 0, iv.Length); Buffer.BlockCopy(cipherTextBytes, 0, combinedBytes, iv.Length, cipherTextBytes.Length); return Convert.ToBase64String(combinedBytes); } } public static string Decrypt(string encryptedText) { if (string.IsNullOrEmpty(encryptedText)) throw new ArgumentNullException(nameof(encryptedText)); // 从Base64字符串还原字节数组 byte[] combinedBytes = Convert.FromBase64String(encryptedText); using (AesCryptoServiceProvider aes = new AesCryptoServiceProvider()) { aes.BlockSize = 128; aes.KeySize = 256; aes.Key = _key; aes.Mode = CipherMode.CBC; aes.Padding = PaddingMode.PKCS7; // 拆分IV和密文(IV长度是16字节,因为BlockSize是128位=16字节) byte[] iv = new byte[16]; byte[] cipherTextBytes = new byte[combinedBytes.Length - iv.Length]; Buffer.BlockCopy(combinedBytes, 0, iv, 0, iv.Length); Buffer.BlockCopy(combinedBytes, iv.Length, cipherTextBytes, 0, cipherTextBytes.Length); aes.IV = iv; // 创建解密器 ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key, aes.IV); // 执行解密 byte[] plainTextBytes; using (MemoryStream ms = new MemoryStream(cipherTextBytes)) { using (CryptoStream cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read)) { using (MemoryStream outputMs = new MemoryStream()) { cs.CopyTo(outputMs); plainTextBytes = outputMs.ToArray(); } } } // 用UTF-8还原字符串,支持希伯来字母 return Encoding.UTF8.GetString(plainTextBytes); } } }
额外注意事项
- 密钥管理:绝对不要硬编码密钥,建议使用安全的密钥存储方案(比如Windows的DPAPI、Azure Key Vault等)。
- IV的重要性:IV必须是随机且唯一的,但不需要保密,可以和密文一起公开传输/存储。
- 资源释放:使用
using语句自动释放AesCryptoServiceProvider和流对象,避免资源泄漏。
内容的提问来源于stack exchange,提问作者riv
相关产品推荐
相关产品推荐

