读取文件内容并加密,然后保存
最后,让我们来看看文件加密的具体细节,如何从文件中读取内容,如何加密,如何将加密后的内容保存到新文件。
请先看下面的代码:
这里重点说一下 54 ~ 61行,这是加密的关键代码。
用户输入的密钥保存在 secretKey 变量,密钥的长度为keyLen(最长为20),fpSource为要加密的文件,fpTarget为存放加密内容的文件。代码一次从fpSource文件中读取keyLen个字节的数据,暂存到缓冲区buffer,将buffer中的数据与密钥secretKey逐字节进行异或运算,再将结果写入到fpTarget。
这里注意:虽然代码期望从fpSource中读取keyLen个字节,但是到文件结尾时读取的字节数可能小于keyLen,所以应该以实际读取到的字节长度readCount为准:
说明:这是最粗糙最容易的加密算法,很容易破解,尤其是要加密的数据只有几个字节时,暴利破解几乎不费吹灰之力。例如,当对字符 'a' 进行加密时,即使输入的密码很长,也只有第一个字节有用,一个字节只有2^8=256种字符,遍历这256个字符,总有一个是对的。
较为安全的加密算法将在《算法》中讲解,这里重在教学演示,让大家知道写代码的思路。
请先看下面的代码:
#include <stdio.h> // 标准输入输出函数 #include <stdlib.h> // 标准库函数 #include <string.h> // 字符串处理函数 int encryptFile(char *sourcefile, char *secretKey, char *targetFile); int main(){ char sourcefile[30], // 加密的文件名 targetFile[30], // 加密后要保存的文件名 secretKey[21]; // 文件加密的密钥 printf("输入要加密的文件名(含路径):"); scanf("%s", sourcefile); printf("输入密钥:"); //密钥是用户自己定义的,可以随意给需要加密的文件添加密钥 scanf("%s", secretKey); printf("加密后的文件名(含路径):"); //给加密后的文件命名,并保存 scanf("%s",targetFile); if( encryptFile(sourcefile, secretKey, targetFile) ){ printf("恭喜你,文件[%s]加密成功,保存在[%s]。\n", sourcefile, targetFile); } } /** * 加密文件 * * @param sourcefile 要加密的文件名 * @param secretKey 密钥 * @param targetFile 加密后要保存的文件名 * * @return 加密成功或失败的数字表示 0:加密失败 1:加密成功 **/ int encryptFile(char *sourcefile, char *secretKey, char *targetFile){ FILE *fpSource, *fpTarget; // 要打开的文件的指针 char buffer[21]; // 缓冲区,用于存放从文件读取的数据 int readCount, // 每次从文件中读取的字节数 keyLen = strlen(secretKey), // 密钥的长度 i; // 循环次数 // 以二进制方式读取/写入文件 fpSource = fopen(sourcefile, "rb"); if(fpSource==NULL){ printf("文件[%s]打开失败,请检查文件路径和名称是否输入正确!\n", sourcefile); return 0; } fpTarget = fopen(targetFile, "wb"); if(fpTarget==NULL){ printf("文件[%s]创建/写入失败!请检查文件路径和名称是否输入正确!\n", fpTarget); return 0; } // 不断地从文件中读取 keyLen 长度的数据,保存到buffer,直到文件结束 while( (readCount=fread(buffer, 1, keyLen, fpSource)) > 0 ){ // 对buffer中的数据逐字节进行异或运算 for(i=0; i<readCount; i++){ buffer[i] ^= secretKey[i]; } // 将buffer中的数据写入文件 fwrite(buffer, 1, readCount, fpTarget); } fclose(fpSource); fclose(fpTarget); return 1; }运行结果:
这里重点说一下 54 ~ 61行,这是加密的关键代码。
用户输入的密钥保存在 secretKey 变量,密钥的长度为keyLen(最长为20),fpSource为要加密的文件,fpTarget为存放加密内容的文件。代码一次从fpSource文件中读取keyLen个字节的数据,暂存到缓冲区buffer,将buffer中的数据与密钥secretKey逐字节进行异或运算,再将结果写入到fpTarget。
这里注意:虽然代码期望从fpSource中读取keyLen个字节,但是到文件结尾时读取的字节数可能小于keyLen,所以应该以实际读取到的字节长度readCount为准:
- 如果readCount=keyLen,那么secretKey的每个字节都会参与异或运算;
- 如果readCount<keyLen,那么secretKey只有前readCount个字节参与异或运算。
- 密钥越长,keyLen越大,破解难度就越大。
说明:这是最粗糙最容易的加密算法,很容易破解,尤其是要加密的数据只有几个字节时,暴利破解几乎不费吹灰之力。例如,当对字符 'a' 进行加密时,即使输入的密码很长,也只有第一个字节有用,一个字节只有2^8=256种字符,遍历这256个字符,总有一个是对的。
较为安全的加密算法将在《算法》中讲解,这里重在教学演示,让大家知道写代码的思路。