一、文件加密与解密实战:简单的异或加密算法实现
说实话,加密这个话题,很多初学者一听就觉得高深莫测。其实没那么玄乎。
我最早接触文件加密,是在一个嵌入式项目里。当时需要把配置参数写到EEPROM里,但又不想让别人直接看到明文。嗯,那时候我就用了一个非常简单的办法——异或加密。
今天咱们就来聊聊这个。你想想看,加密的本质是什么?说白了,就是把原始数据(明文)通过某种规则,变成别人看不懂的东西(密文)。而解密,就是反过来操作,把密文恢复成明文。
异或加密,就是最简单、最基础的一种对称加密算法。
1.1 异或运算的基础
异或,在C语言里用 ^ 这个符号表示。它的运算规则很简单:
- 两个位相同,结果为0
- 两个位不同,结果为1
举个例子:
0 ^ 0 = 0
0 ^ 1 = 1
1 ^ 0 = 1
1 ^ 1 = 0
看起来是不是很简单?但异或有一个非常神奇的特性,我当年第一次发现时还觉得挺有意思的——可逆性。
异或的核心特性:
如果 a ^ b = c,那么 c ^ b = a
也就是说,同一个数异或两次,就能回到原来的值。
这个特性,就是异或加密的数学基础。你拿一个密钥去异或明文,得到密文。再拿同一个密钥去异或密文,就能还原出明文。
1.2 异或加密的原理
咱们用一张图来理解这个过程:
看到没?加密和解密用的是同一个操作。这就是对称加密的特点——加密和解密使用相同的密钥。
1.3 代码实现
好了,理论说完了,咱们直接上代码。我习惯把功能拆得细一点,这样好维护。
#include <stdio.h>
#include <stdlib.h>
// 异或加密/解密函数
// 注意:加密和解密用的是同一个函数
void xor_encrypt_decrypt(const char *input_file,
const char *output_file,
unsigned char key) {
FILE *fin = fopen(input_file, "rb");
if (fin == NULL) {
printf("无法打开输入文件:%s\n", input_file);
return;
}
FILE *fout = fopen(output_file, "wb");
if (fout == NULL) {
printf("无法创建输出文件:%s\n", output_file);
fclose(fin);
return;
}
int ch;
while ((ch = fgetc(fin)) != EOF) {
// 对每个字节进行异或操作
unsigned char encrypted = ch ^ key;
fputc(encrypted, fout);
}
fclose(fin);
fclose(fout);
printf("操作完成!\n");
}
int main() {
unsigned char key = 0xAB; // 随便选一个密钥
printf("=== 文件异或加密/解密演示 ===\n\n");
// 加密
printf("正在加密文件...\n");
xor_encrypt_decrypt("plain.txt", "encrypted.bin", key);
// 解密
printf("正在解密文件...\n");
xor_encrypt_decrypt("encrypted.bin", "decrypted.txt", key);
return 0;
}
小提示:
我在项目中一般用 unsigned char 来存密钥,因为它的范围是0-255,正好一个字节。用 int 也行,但容易出一些隐式类型转换的问题。
1.4 代码详解
咱们一行一行来看:
- 文件打开模式:用的是
"rb"和"wb",也就是二进制模式。为什么要用二进制?因为文本模式在Windows下会做换行符转换,加密时可能会出问题。我踩过这个坑,后来就老老实实全用二进制模式了。 - 逐字节读取:
fgetc一次读一个字节,读到EOF就结束。注意fgetc返回的是int,不是char。为什么?因为EOF是 -1,用char存不下。 - 异或操作:
ch ^ key,就这么简单。一个字节和密钥异或,得到密文。 - 写入文件:
fputc把加密后的字节写出去。
你想想看,整个加密过程,核心代码其实就一行:unsigned char encrypted = ch ^ key;
1.5 运行效果
假设 plain.txt 里写的是 Hello, World!,密钥是 0xAB:
| 阶段 | 文件内容(十六进制) | 说明 |
|---|---|---|
| 明文 | 48 65 6C 6C 6F 2C 20 57 6F 72 6C 64 21 | 原始数据 |
| 密文 | E3 CE C7 C7 C4 87 8B FC C4 D9 C7 CF 8A | 已经看不懂了 |
| 解密后 | 48 65 6C 6C 6F 2C 20 57 6F 72 6C 64 21 | 和原来一模一样 |
注意:
这种加密方式虽然简单,但安全性很低。为什么呢?因为密钥只有一个字节,最多256种可能。用暴力破解的话,几秒钟就能试完。我曾经在一个玩具项目里用过,后来被同事笑话了。
所以,这个算法适合用来学习原理,或者加密一些不太重要的数据。真正要保护敏感信息,还是得用AES、RSA这些成熟的算法。
1.6 改进方向
如果你觉得单字节密钥太弱,可以试试多字节密钥:
void xor_encrypt_multi_key(const char *input_file,
const char *output_file,
const unsigned char *key,
int key_len) {
FILE *fin = fopen(input_file, "rb");
FILE *fout = fopen(output_file, "wb");
int key_index = 0;
int ch;
while ((ch = fgetc(fin)) != EOF) {
unsigned char encrypted = ch ^ key[key_index];
fputc(encrypted, fout);
// 循环使用密钥
key_index = (key_index + 1) % key_len;
}
fclose(fin);
fclose(fout);
}
这样密钥就不是一个字节了,而是一串字节。比如用 "MySecretKey123" 作为密钥,破解难度就大得多了。
核心要点回顾:
- 异或加密利用的是异或运算的可逆性
- 加密和解密使用同一个函数
- 文件操作要用二进制模式("rb"/"wb")
- 单字节密钥不安全,实际应用建议用多字节密钥
嗯,这一章的内容就到这儿。异或加密虽然简单,但它是理解更复杂加密算法的基础。你把这个搞明白了,后面学AES、RSA的时候,就会觉得亲切很多。
公众号:蓝海资料掘金营,微信deep3321