异或加密仅适用于局部文件加密且需固定偏移,因其不改变长度、无需对齐,但无防篡改和防重放能力;必须校验文件大小、实际读取字节数及定位有效性,并以二进制模式操作。

异或加密为什么只适合“部分文件”且必须从固定偏移开始
因为异或本身不改变数据长度,也不需要填充或块对齐,直接按字节和密钥循环异或就行——这正好匹配“从某 offset 开始改一部分”的需求。但反过来说,它完全不防篡改、不防重放,更不能替代 AES 这类完整加密方案;如果你要保护的是配置文件里第 1024 字节起的 token 字段,xor 合理;如果想防逆向或传输窃听,它连门槛都算不上。
- 密钥长度任意,但建议用
std::vector存,别用 C 风格字符串(末尾\0会截断) - 偏移量
offset和长度len必须在文件大小范围内,否则读写越界——std::ifstream::seekg不报错,但后续read()可能返回 0 字节 - 务必用二进制模式打开文件:
std::ios::binary,否则 Windows 下\r\n转换会破坏原始字节流
如何安全地读取+修改文件指定区域(C++ ifstream / ofstream)
不能先读整个文件再改再写回——大文件耗内存,且“只改中间一段”时没必要。正确做法是:以 inout 模式打开,seekp 定位,write 覆盖。但注意:fstream 的 in | out 模式默认不支持直接覆盖(某些平台会清空文件),稳妥方案是分开读写,或用 in | out | binary + seekg/seekp 同步。
- 先用
std::ifstream以binary模式读取原始数据块(从offset开始,len字节) - 对这块内存做
xor运算(密钥逐字节循环,用key[i % key.size()]) - 再用
std::ofstream以binary | in | out模式打开,seekp(offset),write()写回 - 别忘了检查
is_open()和good(),尤其seekp后要确认tellp() == offset,避免定位失败却静默继续
常见错误:密钥循环错位、字节序混淆、文件截断
最常踩的坑不是算法逻辑,而是 I/O 边界处理。比如用 std::string 当密钥,里面混入 \0,size() 返回值就错了;或者把 offset 当成行号传进去,结果 seek 到了错误位置;还有人用 ofstream 默认构造打开文件,没加 ios::in,导致文件被清空。
-
std::string key = "\x01\x02\x00\x03"→ 实际长度是 3(\0截断),但你想用 4 字节密钥 → 改用std::vector{0x01,0x02,0x00,0x03} - 写入前没调
flush()或没关闭流,系统缓存未落盘,下次读还是旧数据 - 目标文件原本只有 1000 字节,你设
offset=500, len=800→ 实际只能读到 500 字节,但代码仍对 800 字节做 xor → 后 300 字节是栈垃圾值 → 写回去就损坏文件
C++ 示例:只加密文件第 2048 字节起的 128 字节
下面这段代码只做一件事:定位、读、xor、写回。没有封装类,不依赖第三方库,所有路径、偏移、密钥都硬编码便于对照逻辑。
#include <fstream>
#include <vector>
#include <iostream><p>int main() {
const std::string path = "config.bin";
const size_t offset = 2048;
const size_t len = 128;
const std::vector<uint8_t> key = {0xDE, 0xAD, 0xBE, 0xEF};</uint8_t></p>
<pre class="brush:php;toolbar:false;">std::ifstream fin(path, std::ios::binary);
if (!fin.is_open()) { std::cerr file_size || len > file_size - offset) {
std::cerr buf(len);
fin.read(reinterpret_cast<char>(buf.data()), len);
if (fin.gcount() != static_cast<:streamsize>(len)) {
std::cerr (buf.data()), len);
fout.close();
return 0;</:streamsize></char>
}
关键点就三个:file_size 校验、gcount() 检查实际读取字节数、seekp 后不假设一定成功。其他都是围绕它们服务的防御性写法。
真正难的不是 xor 本身,是确保你操作的那几 KB 确实是你以为的那几 KB——磁盘、缓存、文件系统、C++ 流状态,任何一环掉链子,加密就变成误伤。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











