c++中如何实现简单加密算法_c++异或加密与Base64编码方法【详解】

异或加密不能直接用于网络传输,因其结果含控制字符(如\0、\n)易被HTTP/JSON等截断或转义;必须经Base64等文本安全编码后方可传输。

为什么异或加密不能直接用于网络传输

异或加密(XOR)本身是可逆的、无损的,但结果是原始字节流,其中可能包含 \0\n\r 或 ASCII 控制字符(如 0x010x1F),这些在 HTTP、JSON、XML、日志打印甚至某些文件系统中会被截断、转义或静默丢弃。直接传输 xor_encrypt("hello", 0xFF) 得到的 \x68\x65\x6c\x6c\x6f 异或后可能是 \x97\x9a\x93\x93\x90——这个序列在终端里无法显示,用 std::cout 输出会提前终止。

  • 必须将二进制密文转换为纯文本安全格式,Base64 是最常用选择
  • 不要把 XOR 当成“加密算法”来用,它没有密钥调度、无扩散性,仅适合临时混淆或教学演示
  • 若需真实安全,请用 libsodiumOpenSSLAES-256-GCM

手写 Base64 编码要注意的 3 个边界

C++ 标准库不带 Base64,手写时最常出错的是填充和越界读取。Base64 每 3 字节输入编码为 4 字符输出,所以输入长度不是 3 的倍数时必须补 \0 并用 = 填充。常见错误包括:

  • 对长度为 1 的输入(如单字节)只补 2 个 \0,但解码时未检查末尾 = 数量,导致读越界
  • 查表使用 std::string 索引(如 ta

    ble[i]
    ),但 i 可能为负或 >63,没做范围校验
  • 忽略平台字节序影响——其实 Base64 只处理字节,与 endianness 无关,但有人误把 int 直接 cast 成 char* 导致高位字节错位

一个安全可用的 XOR+Base64 组合示例

以下代码满足:支持任意长度输入、正确 Base64 填充、不依赖第三方、可直接编译(C++17)。关键点是 xor_encrypt 返回 std::vector,再喂给 base64_encode,避免中间 string 截断:

std::string base64_encode(const std::vector& data) {
    static const char table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
    std::string out;
    int val = 0, valb = -6;
    for (uint8_t c : data) {
        val = (val << 8) + c;
        valb += 8;
        while (valb >= 0) {
            out.push_back(table[(val >> valb) & 0x3F]);
            valb -= 6;
        }
    }
    if (valb > -6) out.push_back(table[((val << 8) >> (valb + 8)) & 0x3F]);
    while (out.size() % 4) out.push_back('=');
    return out;
}

std::vector xor_encrypt(const std::string& input, uint8_t key) {
    std::vector out(input.size());
    for (size_t i = 0; i < input.size(); ++i) {
        out[i] = static_cast(input[i]) ^ key;
    }
    return out;
}

// 使用:
std::string plain = "secret123";
auto cipher_bytes = xor_encrypt(plain, 0x5A);
std::string encoded = base64_encode(cipher_bytes); // 如 "qJmZkZmZkY=="

Base64 解码后必须验证 XOR 密钥一致性

Base64 解码得到的是原始密文字节,但如果你不知道加密时用的 key,就无法还原。实际项目中常见错误是把 key 硬编码在客户端,又忘了和服务端对齐——比如服务端用 0x5A,客户端用了 0x5a(小写 a ASCII 是 97),结果解出来全是乱码。更隐蔽的问题是:

  • 字符串字面量默认是 const char*,传入 std::string 构造函数时若含 \0 会被截断,导致 key 长度意外变短
  • 异或操作对大小写敏感,'A''a' 差 32,用错一个字母,整个明文全崩
  • Base64 解码函数若未处理 = 填充数量(1 或 2 个),会导致输出长度错误,XOR 解密时访问越界

真正难的不是写对一次,而是让加解密两端在不同编译器、不同 C++ 标准版本下行为一致——建议所有字节操作统一用 uint8_t,别混用 charunsigned char