利用按位异或运算加密文件(用c语言、c++和vb写的)-创新互联

这是我用来练习的程序,功能是用密码加密文件,写了两个版本:第一个完全用c++写,练习类的继承、操作符重载;第二个尝试用c写dll,vb调用dll的函数。

专注于为中小企业提供成都网站设计、成都网站制作服务,电脑端+手机端+微信端的三站合一,更高效的管理,为中小企业达州免费做网站提供优质的服务。我们立足成都,凝聚了一批互联网行业人才,有力地推动了千余家企业的稳健成长,帮助中小企业通过网站建设实现规模扩充和转变。
原理

在第一次学按位异或算符“^”时,我注意到这个运算是可逆的,即(a^b)^b=a,于是就想到可以利用按位异或运算将文件加密。后来就写了加密程序,原理是用特定长度的char类型作为密码,将文件内容与密码逐字节异或运算,将运算结果写入另一个文件,密码长度不够就从头循环。

c0356b1388ea41cbb4fd9e78203d17a2.png

可以看出,将加密后的文件用相同的密码再次“加密”后就可以解密。


密码形式

密码形式是二进制文件“key.bin”。char类型可以放不可打印字符,于是我想到从二进制文件中读取密码,用16进制编辑器编辑二进制文件(我用的是flexhexeditor)。二进制文件的前4个字节是unsigned int型变量,是密码长度,密码长度不能太长,我初步定为不超过256字节;从第5个字节开始到文件结尾就是密码,文件末尾多出一些内容也没关系。


加密后的文件名

保存的文件文件名,我是直接加一个扩展名“.加密文件”,如果文件本身扩展名就是“.加密文件”,就把扩展名去掉。


两个版本的区别

c++版是将文件拖动到exe程序上打开,程序在工作目录打开“key.bin”(如果是拖动打开或选择打开方式后双击打开,则工作目录为文件所在目录)。c和vb版是可以选择文件,用的是winapi函数GetOpenFileName。另外c和vb版可以输入字符串作为密码,或者从bmp文件产生密码,是当时考虑各种密码形式时的产物。

c++代码如下,vb和c混合写的由于有多个文件,不贴代码,发文件:按位异或文件加密,vb

#include#include#include#include//尝试类继承的练手作
#define scanlength 65536

class keychar;

class mywords {
	protected:
		unsigned int length;//字节数
		char *str;
	public:
		mywords(char * words, int length = 0);
		mywords(int len);
		mywords();
		~mywords();
		int read(std::ifstream &in);//默认从文件中读取length字节的内容 
		int read(std::ifstream &in, int len);//指定读取的长度
		void write(std::ofstream &out, int len);//将str指向的len字节内容写入文件
		unsigned int getlength();
		mywords& operator =(mywords& words);
		mywords& operator =(char* words);
		//因为字节数不一定相等,mywords的按位异或运算不满足交换律
		mywords& operator ^=(keychar& key);
};

class keychar : public mywords {
	public:
		static const int keychar_size = 256;
		void keyread(std::ifstream &in);
		void keywrite(std::ofstream &out);
};

int main(int argc, char *argv[]) {
	int n;
	mywords scan(scanlength); //在一定范围内,scanlength越长,速度越快 
	keychar key;
	std::ifstream in, keyin;
	std::ofstream out;
	if (argc >1) {
		//识别扩展名,有".加密文件"则删,无则追加
		char *file;
		file = strrchr(argv[1], '\\') + 1;//每层文件夹后都有\,所以定位到最后一个 
		char filename[strlen(file) + 64];//预留一些空间,防止内存溢出 
		strcpy(filename, file);
		file = strrchr(filename, '.');//定位到最后一个'.',就是扩展名,“电影.mp4.txt”是纯文本文件 
		if (!file || strcmp(file, ".加密文件")) {
			strcpy(filename + strlen(filename), ".加密文件");
		} else {
			*file = '\0';
		}
		//打开文件
		in.open(argv[1], std::ios::binary);
		out.open(filename, std::ios::binary);
		keyin.open("key.bin", std::ios::binary);
		//读取key文件
		if (keyin) {
			key.keyread(keyin);
			keyin.close();
		}
		//读取文件并加密保存
		while (!in.eof()) {
			n = scan.read(in);
			scan ^= key;
			scan.write(out,n);
		}
	}
	in.close();
	out.close();
	return 0;
}

mywords::mywords() {
	length = 0;
	str = NULL;
}

mywords::mywords(int len) {
	length = len;
	str = (char*)malloc(length);
}

mywords::mywords(char*words, int length) {
	if (length< 1)length = strlen(words);
	str = (char*)malloc(length);
	for (int i = 0; i< length; i++) {
		str[i] = words[i];
	}
}

mywords::~mywords() {
	if (str)free(str);
}

int mywords::read(std::ifstream &in){
	in.read(str,length);
	return in.gcount();
}

int mywords::read(std::ifstream &in, int len){
	in.read(str,len);
	return in.gcount();
}

void mywords::write(std::ofstream &out, int len){
	out.write(str,len);
}

unsigned int mywords::getlength() {
	return length;
}

mywords& mywords::operator ^=(keychar& key) {
	unsigned int i, j;
	if (key.getlength() >0)
		for (i = j = 0; i< length; i++, j++) {
			if (j >= key.getlength())j -= key.getlength();
			str[i] ^= key.str[j];
		}
	return *this;
}

mywords& mywords::operator =(mywords& words) {
	unsigned int i;
	length = words.length;
	if (str)free(str);
	str = (char *)malloc(length);
	for (i = 0; i< words.length; i++)str[i] = words.str[i];
	return *this;
}

mywords& mywords::operator =(char* words) {
	unsigned int i;
	length = strlen(words);
	if (str)free(str);
	str = (char*)malloc(length);
	for (i = 0; i< length; i++)str[i] = words[i];
	return *this;
}

void keychar::keyread(std::ifstream &in) {
	if (str)free(str);
	length = 0;
	str = NULL;
	in.read((char*)&length, 4);
	if (length >keychar_size)
		length = ((length & 0xff)<< 24) + ((length & 0xff00)<< 8) + ((length & 0xff0000) >>8) + ((length & 0xff000000) >>24);
	if (length >keychar_size) {
		printf("error: key文件格式错误,不加密(解密)输出\n");
		system("pause");
	}
	if (length) {
		str = (char*)malloc(length);
		in.read(str, length);
	}
}

void keychar::keywrite(std::ofstream &out) {
	out.write((char*)&length, 4);
	if (length)out.write(str, length);
}

你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧


文章标题:利用按位异或运算加密文件(用c语言、c++和vb写的)-创新互联
网站网址:http://azwzsj.com/article/dgoscc.html