赞
踩
严格意义上的加密算法有对称加密算法和非对称加密算法,对称加密算法是指加密与解密的key相同,而非对称加密算法是指加密(使用公钥,所有人都可以获取)与解密(使用私钥,只有指定方有私钥)的key不相同。这种严格的加密算法依赖于矩阵乘法进行数据加密,运算量较大,通常适用于短信息的加密,而针对于长信息(较大的文件)则不适用(具体可以参考压缩文件的加密)。
加密的本质就是对信息进行混淆,使拿到数据的人无法有效的识别出原始信息;而解密则是将混淆后的信息进行还原。因此,可以基于对信息的混淆进行数据加密。进行本工作前,博主进行粗略调查,c++实现文件加密的有以下方法:
1、基于异或操作的加密;https://blog.csdn.net/zhaxun/article/details/125027503
2、基于取反操作的加密;https://blog.csdn.net/weixin_50964512/article/details/123977481
3、基于ascall码表的加密;https://blog.csdn.net/weixin_46897073/article/details/110410141
这些加密方法的第一操作原理在于将文件以二进制的方式读取为char数组(每个char对应一个ascall值),相关c++代码如下
vector<char> read_file(string fname) {
//读取文件
ifstream inFile(fname, ios::in | ios::binary | ios::ate);
long size = inFile.tellg();
inFile.seekg(0, ios::beg);
vector<char> buffers(size);
inFile.read(buffers.data(), size);
inFile.close();
return buffers;
}
通过对现行三个文件加密方法的思考,认为实现加密解密算法的本质就是定义一个数据混淆规则,这个规则应该有一个人为参与的code,而且这个code不能太短。在进行加密时,根据code进行相应的操作。
考虑到基于密码表的加密限制了code的范围;使用异或操作的加密则使code的值变得更小。博主以对vector的操作为思考起点。
共得出以下基本的数据混淆操作:
//取反操作 void reverse_value(vector<char>& data) { for (int i = 0; i < data.size();i++) { data[i] = 255 - data[i]; } } //倒序操作 void reverse_sort(vector<char>& data) { reverse(data.begin(), data.end()); } //滑动操作 //根据start对vector进行截断, 让datain=dataout2+dataout1既实现了滑动操作 void vector_cut(vector<char>& datain, long start, vector<char>& dataout1, vector<char>& dataout2) { dataout1.assign(datain.begin(), datain.begin() + start); dataout2.assign(datain.begin() + start, datain.end()); } //重载vector的运算符 template <typename T> vector<T>& operator +(vector<T>& v1, vector<T>& v2) { v1.insert(v1.end(), v2.begin(), v2.end()); return v1; }
考虑到加密方法需要用户参与,将code设为多个数字。加密时,代码根据code中的数字对数据进行切分(用于实现滑动操作)得到切片1和切片2,对切片1进行取反操作,对切片2进行倒序操作;解密时,代码根据code中的数字对数据进行切分(用于实现滑动操作)得到切片1和切片2,对切片1进行倒序操作,对切片2进行取反操作。
由于加密和解密的基本操作都是一样,且都依赖于滑动操作。故,所实现的加密和解密方法如下。其中,datain表示输入的数据,start表示滑动的位置,encode=true表示进行加密操作,false表示进行解密操作。这里考虑到每个数据的size可能不一样,使用固定的start可能会超出数据的长度,故以百分比描述滑动的位置。当srart>=100时为无效值
void move_vector(vector<char>& datain, int start, bool encode = true) { vector<char> data1, data2; if (start >= 100) {//大于等于100不进行任何操作 return; } start = int(start * datain.size() / 100); if (!encode) { //解码时的位置要调整 start = datain.size() - start; } vector_cut(datain, start, data1, data2); if (!encode) { //解码时的位置要调整 reverse_sort(data1); reverse_value(data2); } else { reverse_sort(data2); reverse_value(data1); } datain = data2 + data1;//交换这一段的位置 }
这里的设定是基于code进行加密,多个code则对应了多次加密次数,这使得数据基本上不可能被还原(打乱顺序比较简单,从混乱的数据中恢复顺序比较困难)。
code为加密规则,示例:“13 41 54 19 12 4 42 54”,可以为任意长度,以空格分开每一个值
void encry_data(vector<char>& data, string code) {
vector<string> codes = split_char(code, ' ');
for (int i = 0; i < codes.size(); i++) {
int offset;
convertFromString(offset, codes[i]);
move_vector(data, offset);
}
}
与encry_data函数共用相同的code,只是倒序进行操作
void decry_data(vector<char>& data, string code) {
vector<string> codes = split_char(code, ' ');
for (int i = codes.size() - 1; i >= 0; i--) {
int offset;
convertFromString(offset, codes[i]);
move_vector(data, offset, false);
}
}
这里对二进制文件进行加密示意。二进制文件的原始内容如下
加密解密代码如下:
#include "EncryFile.hpp"
using namespace std;
int main() {
string fname = "C:/Users/xxx/Pictures/a.txt";
string codes = "18 5 63 41 22";//文件的加密码
string fencry= "C:/Users/xxx/Pictures/a_en.txt";
string fdecry = "C:/Users/xxx/Pictures/a_de.txt";
encry_file(fname, codes, fencry);
decry_file(fencry, codes, fdecry);
return 0;
}
加密后的内容如下,可以看到部分内容已经倒序,部分内容已经取反;而且出现了空行,数据的行数与原来无法对应。在不知道数据混淆规则(code)的情况下对数据进行还原是异常困难的。
具体加密代码如下
#include "EncryFile.hpp"
using namespace std;
int main() {
string fname = "C:/Users/xxx/Pictures/bj.bmp";
string codes = "18 5 63 41 22";//文件的加密码
string fencry= "C:/Users/xxx/Pictures/bj_encry.bmp";
string fdecry = "C:/Users/xxx/Pictures/bj_decry.bmp";
encry_file(fname, codes, fencry);
decry_file(fencry, codes, fdecry);
return 0;
}
最终加密解密效果如下所示,可以看到计算机已经无法有效识别bj_encry.bmp(对于特定格式的文件,进行混淆后是无法被原来的软件进行解析的的(因为出现了数据错位、数据值部分取反、数据局部顺序翻转)
)。这表明这种数据加密规则是可以应用到绝大部分文件中。
补充:在本博文中有4个非重要函数并未公开。各位可以下载我的(付费资源)使用完整代码,或者自行根据以下代码提示补齐函数。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。