近来写了一个有关加密文本的加密程序,基本原理是将文件中所有字节和指定的密码逐字节进行异或,一般文件内容远远长于密码,那么可以扩展密码为:123456123456…这种循环的形式,直到和原文件相同的长度。这样所有文件的内容对被密码加密了,而且由于异或的特性,只需要再执行一下加密的过程,原文件内容就可以被恢复。
下面写一下实现的具体功能,主要函数和效果:
程序可以将程序文件所在文件夹以及子文件夹下,所有后缀为txt和docx的文件进行加密,加密文件后缀变为txtenc,docxenc如果存在需要加密的文件则进行加密(加密文件和未加密文件都在文件夹下时也进行加密),如果所有txt和docx文件都是加密文件,那就通过像用户询问密码来确认是否解密。
vector<string> file_set;
这里定义了一个字符串数组,来存储文件夹下所有满足要求的文件名。
void handle_all_file(string path, vector<string> &file_set)
{
long hFile = 0;
struct _finddata_t fileInfo;
string pathName;
if((hFile = _findfirst(pathName.assign(path).append("\\*").c_str(), &fileInfo)) == -1) return ;
do{
if( strcmp(fileInfo.name,"..") && strcmp(fileInfo.name,".") && fileInfo.attrib==_A_SUBDIR )
handle_all_file(path+"\\"+fileInfo.name, file_set);
if (compare_file_name(fileInfo.name, ".txt") || compare_file_name(fileInfo.name, ".docx"))
{
encry = true;
file_set.push_back(path+"\\"+fileInfo.name);
}else if(compare_file_name(fileInfo.name, ".txtenc") || compare_file_name(fileInfo.name, ".docxenc")){
file_set.push_back(path+"\\"+fileInfo.name);
}
}while(_findnext(hFile, &fileInfo)==0);
_findclose(hFile);
return;
}
这里通过结构体_finddata_t来列出所有文件名,它的使用参考了
https://blog.csdn.net/godop/article/details/81080835
compare_file_name是对文件名后缀简单判断,存在符合要求的未加密文件时,让一个全局bool变量encry赋予值true,用于判断执行加密过程还是解密。这个函数将加密文件和未加密文件都挑选出来,所以后继需要根据encry的值判断是对加密文件解密还是对未加密文件加密。
void encry_deencry(vector<string> &file)
{
if(!encry)
{
cout<<"please input password:"<<endl;
char tempkey[10] = {0};
cin>>tempkey;
if(strcmp(tempkey, key) != 0)
return;
else{
cout << "Right!" << endl;
}
}
for(vector<string>::iterator filei=file.begin(); filei != file.end(); ++filei)
{
string filej = *filei;
if(encry && (compare_file_name(filej.c_str(), ".txt"))||(compare_file_name(filej.c_str(), ".docx")))
handle_one_file(filej);
if((!encry) && (compare_file_name(filej.c_str(), ".txtenc"))||(compare_file_name(filej.c_str(), ".docxenc")))
handle_one_file(filej);
}
}
这个函数是询问密码判断密码是否正确,再度挑选出合适的文件,进行处理。
int handle_one_file(string path)
{
cout << path <<endl;
string path1, path2;
if(encry)
{
path1 = path;
path2 = path+"enc";
}else
{
path1 = path;
path2 = path1.substr(0, path1.length()-3);
}
cout << path1 << "------" << path2 << endl;
FILE *f = fopen(path1.c_str(), "rb");
FILE *fw = fopen(path2.c_str(), "wb");
const int buffer_size = 1024;
int read_size = 0;
char buffer[1024+1] = {0};
int i;
memset(buffer, 0, buffer_size+1);
while (read_size = fread(buffer, sizeof (char), buffer_size, f)) {
for(i = 0; i<read_size; i++){
buffer[i] ^= key[i%strlen(key)];
}
fwrite(buffer, sizeof (char), read_size, fw);
}
fclose(f);
fclose(fw);
remove(path1.c_str());
return 0;
}
通过C语言的fopen,fread,fwrite,读出文件然后通过key[i%strlen(key)]循环地用密码取异或原始文件内容。
完整代码如下:
#include
#include
#include
#include
#include
#include
#include
using namespace std;
char key[] = "123456";
bool encry = false;
bool compare_file_name(const char *s, char *den)
{
return strrchr(s, '.')&&(strcmp(strrchr(s, '.'), den)==0);
}
int handle_one_file(string path)
{
cout << path <<endl;
string path1, path2;
if(encry)
{
path1 = path;
path2 = path+"enc";
}else
{
path1 = path;
path2 = path1.substr(0, path1.length()-3);
}
cout << path1 << "------" << path2 << endl;
FILE *f = fopen(path1.c_str(), "rb");
FILE *fw = fopen(path2.c_str(), "wb");
const int buffer_size = 1024;
int read_size = 0;
char buffer[1024+1] = {0};
int i;
memset(buffer, 0, buffer_size+1);
while (read_size = fread(buffer, sizeof (char), buffer_size, f)) {
for(i = 0; i<read_size; i++){
buffer[i] ^= key[i%strlen(key)];
}
fwrite(buffer, sizeof (char), read_size, fw);
}
fclose(f);
fclose(fw);
remove(path1.c_str());
return 0;
}
void encry_deencry(vector<string> &file)
{
if(!encry)
{
cout<<"please input password:"<<endl;
char tempkey[10] = {0};
cin>>tempkey;
if(strcmp(tempkey, key) != 0)
return;
else{
cout << "Right!" << endl;
}
}
for(vector<string>::iterator filei=file.begin(); filei != file.end(); ++filei)
{
string filej = *filei;
if(encry && (compare_file_name(filej.c_str(), ".txt"))||(compare_file_name(filej.c_str(), ".docx")))
handle_one_file(filej);
if((!encry) && (compare_file_name(filej.c_str(), ".txtenc"))||(compare_file_name(filej.c_str(), ".docxenc")))
handle_one_file(filej);
}
}
void handle_all_file(string path, vector<string> &file_set)
{
long hFile = 0;
struct _finddata_t fileInfo;
string pathName;
if((hFile = _findfirst(pathName.assign(path).append("\\*").c_str(), &fileInfo)) == -1) return ;
do{
if( strcmp(fileInfo.name,"..") && strcmp(fileInfo.name,".") && fileInfo.attrib==_A_SUBDIR )
handle_all_file(path+"\\"+fileInfo.name, file_set);
if (compare_file_name(fileInfo.name, ".txt") || compare_file_name(fileInfo.name, ".docx"))
{
encry = true;
file_set.push_back(path+"\\"+fileInfo.name);
}else if(compare_file_name(fileInfo.name, ".txtenc") || compare_file_name(fileInfo.name, ".docxenc")){
file_set.push_back(path+"\\"+fileInfo.name);
}
}while(_findnext(hFile, &fileInfo)==0);
_findclose(hFile);
return;
}
int main()
{
vector<string> file_set;
handle_all_file(".", file_set);
encry_deencry(file_set);
return 0;
}