异或加密需手写循环,用 unsigned char 处理字节,密钥多字节并取模,加解密逻辑相同;禁用 std::string 存二进制,调试时用 static_cast。

用 std::xor_ 实现不了,得手写异或循环
标准库没有叫 xor_encrypt 的函数,std::xor_ 也不是加密工具——它只是 std::transform 的一个预设二元操作符,连密钥都没法传。真要异或加密,就是遍历每个字节,和密钥字节逐个 ^。
- 密钥通常用
std::string或const char*表示,长度建议至少 1 字节,但单字节密钥(如'A')等价于凯撒位移,毫无安全性 - 推荐用多字节密钥(比如
"key123"),然后对明文索引取模:plaintext[i] ^ key[i % key_len] - 注意:异或加解密是同一逻辑,
encrypt(encrypt(data, k), k) == data,所以别漏掉解密时也用同样密钥和循环方式
char 类型有符号性会破坏异或结果
如果用 char 数组存数据,而编译器默认 char 是有符号的(比如 MSVC、部分 ARM 工具链),那么 0xFF 会被解释成 -1,再参与 ^ 运算时先整型提升为 int(-1),导致高位补 1,最终结果错乱。
- 始终用
unsigned char处理字节数据,包括明文、密文、密钥缓冲区 - 读文件进内存时,别用
std::string直接接收二进制内容(它把\0当结束符),改用std::vector<unsigned char></unsigned>或std::basic_string<unsigned char></unsigned> - 打印调试时,用
static_cast<int>(c)</int>而不是直接std::cout ,否则可能输出不可见字符或截断
异或加密不能替代真正加密,别用在真实场景
它连「混淆」都勉强——已知明文攻击下,只要拿到一段明文+对应密文,立刻能还原出密钥流;如果密钥短且重复使用,还能用重合指数等方法分析。它只适合教学演示、配置项临时掩码、或游戏里防玩家直接搜内存字符串。
- 别用它保护密码、token、API key 等任何敏感字段
- 别把它和
AES、ChaCha20混为一谈;前者是玩具,后者需完整实现、密钥派生、IV 管理、认证加密(AEAD) - 如果真需要轻量加密,优先考虑 OpenSSL 的
EVP_EncryptInit_ex或 libsodium 的crypto_secretbox_easy,而不是自己“加强”异或
一个安全边界的最小可运行示例
下面这段代码只做一件事:把输入字符串按字节和密钥循环异或,输出十六进制形式便于验证。它避开 char 符号陷阱,不依赖外部库,也不假装能防攻击。
立即学习“C++免费学习笔记(深入)”;
#include <vector>
#include <iostream>
#include <iomanip>
std::vector<unsigned char> xor_crypt(const std::vector<unsigned char>& data,
const std::string& key) {
if (key.empty()) return data;
std::vector<unsigned char> out = data;
for (size_t i = 0; i < data.size(); ++i) {
out[i] = data[i] ^ static_cast<unsigned char>(key[i % key.size()]);
}
return out;
}
int main() {
std::vector<unsigned char> plain = {'H', 'e', 'l', 'l', 'o', 0x00, 0xFF};
auto cipher = xor_crypt(plain, "abc");
for (auto b : cipher) {
std::cout << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(b);
}
std::cout << "\n";
}
关键点就三个:unsigned char 类型、key[i % key.size()] 循环、输出前转 int 避免符号扩展。其余全是干扰项。
异或本身很简单,麻烦的是怎么不让它在边界上崩——类型、内存表示、用途预期,三者错一个,结果就不可控。









