利用按位异或运算加密文件(用c语言、c++和vb写的)-创新互联
这是我用来练习的程序,功能是用密码加密文件,写了两个版本:第一个完全用c++写,练习类的继承、操作符重载;第二个尝试用c写dll,vb调用dll的函数。
专注于为中小企业提供成都网站设计、成都网站制作服务,电脑端+手机端+微信端的三站合一,更高效的管理,为中小企业达州免费做网站提供优质的服务。我们立足成都,凝聚了一批互联网行业人才,有力地推动了千余家企业的稳健成长,帮助中小企业通过网站建设实现规模扩充和转变。原理
在第一次学按位异或算符“^”时,我注意到这个运算是可逆的,即(a^b)^b=a,于是就想到可以利用按位异或运算将文件加密。后来就写了加密程序,原理是用特定长度的char类型作为密码,将文件内容与密码逐字节异或运算,将运算结果写入另一个文件,密码长度不够就从头循环。
可以看出,将加密后的文件用相同的密码再次“加密”后就可以解密。
密码形式
密码形式是二进制文件“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://pwwzsj.com/article/dgoscc.html