利用按位异或运算加密文件(用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<fstream>
#include<malloc.h>
#include<string.h>

#include<stdio.h>
//尝试类继承的练手作
#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);
}

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值