Xor加密解密失败主因是编码不统一和密钥未循环对齐;必须始终显式使用Encoding.UTF8等一致编码,且密钥字节数组需循环复用以匹配数据长度。

用 Xor 加密字符串时,为什么加密后乱码或解密失败?
因为 Xor 本身不改变字节长度,但直接对字符串做 Xor 容易踩两个坑:一是没统一编码(比如 string 转 byte[] 时用了不同 Encoding),二是密钥长度没对齐导致错位。实际中多数人用 Encoding.UTF8.GetBytes() 加密,却用 Encoding.Default 解密,结果一串问号或异常。
- 始终显式指定编码,推荐
Encoding.UTF8,避免系统默认编码差异 - 密钥要转成字节数组,并循环复用(不能只取第一个字节)
- 加密/解密必须用同一套逻辑,
Xor是对称操作,但编码步骤错一点就全崩
示例:
var data = Encoding.UTF8.GetBytes("hello");<br>var key = Encoding.UTF8.GetBytes("key");<br>for (int i = 0; i < data.Length; i++) {<br> data[i] ^= key[i % key.Length];<br>}<br>var result = Encoding.UTF8.GetString(data); // 注意:这步仅用于调试,真实场景别这么转回 string
Convert.ToBase64String 是必须的吗?
是。原始 Xor 结果是任意字节流,可能含 <p>是。原始 <code>Xor 结果是任意字节流,可能含 \0、控制字符甚至不可见字节,直接当字符串处理会截断或出错。比如 GetString() 遇到 \0 就停,Console.WriteLine 可能静默丢数据。所以加密后务必用 Convert.ToBase64String 编码,解密前用 Convert.FromBase64String 还原。
GetString() 遇到 <p>是。原始 <code>Xor 结果是任意字节流,可能含 \0、控制字符甚至不可见字节,直接当字符串处理会截断或出错。比如 GetString() 遇到 \0 就停,Console.WriteLine 可能静默丢数据。所以加密后务必用 Convert.ToBase64String 编码,解密前用 Convert.FromBase64String 还原。 就停,Console.WriteLine 可能静默丢数据。所以加密后务必用 Convert.ToBase64String 编码,解密前用 Convert.FromBase64String 还原。
- 不编码 → 无法安全传输、存数据库、写文件
- 别用
Encoding.ASCII.GetString替代,它会把非 ASCII 字节转成? - Base64 输出是纯可打印字符,兼容性好,无歧义
C# 里怎么让 Xor 加密支持中文和特殊符号?
靠编码,不是靠算法改写。只要输入字符串统一走 Encoding.UTF8.GetBytes(),Xor 本身对任何字节都有效——中文在 UTF-8 下占 3 字节,标点符号也是标准字节序列,Xor 按字节算,完全无感。
- 测试时别用
"你好"直接ToString()看效果,要打日志看 Base64 结果是否等长 - 如果发现加密后长度异常,先检查是不是误用了
Encoding.Unicode(UTF-16),它会让英文也变双字节,密钥对齐逻辑就得同步调整 - 不需要额外判断字符类型,
Xor是纯字节运算,字符集问题全由编码层兜住
为什么说 Xor 加密只适合教学或临时掩码?
它没有密钥派生、无随机盐、无完整性校验,重复明文永远生成相同密文,容易被频率分析或已知明文攻击。比如你总用 "SUCCESS" 当响应体,攻击者抓几次包就能反推密钥。
- 生产环境该用
Aes.Create()配合ICryptoTransform,哪怕只是简单封装 - 如果真要轻量,至少加个随机 IV 并随密文一起传输(
Xor本身不支持 IV,硬加就得自己拼接) - 别把
Xor密钥写死在代码里,更别用常量字符串当密钥——反编译一眼就看见
真正难的不是写对 Xor 循环,而是想清楚数据生命周期里哪一环需要保护、谁可能接触中间态、以及出问题时有没有回溯手段。


















