admin管理员组文章数量:1639831
严格意义上的加密算法有对称加密算法和非对称加密算法,对称加密算法是指加密与解密的key相同,而非对称加密算法是指加密(使用公钥,所有人都可以获取)与解密(使用私钥,只有指定方有私钥)的key不相同。这种严格的加密算法依赖于矩阵乘法进行数据加密,运算量较大,通常适用于短信息的加密,而针对于长信息(较大的文件)则不适用(具体可以参考压缩文件的加密)。
1、现有通行的加密方法
加密的本质就是对信息进行混淆,使拿到数据的人无法有效的识别出原始信息;而解密则是将混淆后的信息进行还原。因此,可以基于对信息的混淆进行数据加密。进行本工作前,博主进行粗略调查,c++实现文件加密的有以下方法:
1、基于异或操作的加密;https://blog.csdn/zhaxun/article/details/125027503
2、基于取反操作的加密;https://blog.csdn/weixin_50964512/article/details/123977481
3、基于ascall码表的加密;https://blog.csdn/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只有8位,256个值;如果加密方式泄露,很容易通过碰撞检测进行解密;
- 基于取反操作的加密 其加密与解密过程是一样的;不存在加密的code,针对整个文件进行取反很容易被识别出来
- 基于ascall码表的加密 加密时的密码表必须为256,且不能重复(这对于使用上比较困难);通过很容易通过频率统计分析出密码表
2、所设计的加密方法
通过对现行三个文件加密方法的思考,认为实现加密解密算法的本质就是定义一个数据混淆规则,这个规则应该有一个人为参与的code,而且这个code不能太短。在进行加密时,根据code进行相应的操作。
2.1 可用的混淆操作
考虑到基于密码表的加密限制了code的范围;使用异或操作的加密则使code的值变得更小。博主以对vector的操作为思考起点。
共得出以下基本的数据混淆操作:
- 取反操作 将数据进行取反;解密操作也是取反操作;以单个char为操作单元
- 倒序操作 将数组的顺序进行翻转;解密操作也是倒序操作;以char数组为操作单元
- 滑动操作 将数组首位相连,进行一定的转动;解密操作也是滑动操作;以char数组为操作单元;(如,滑动值为20%,则将数组前20%的数据截取下来放到最后面)
以上三个操作的实现代码如下
//取反操作
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;
}
2.2 加密方法
考虑到加密方法需要用户参与,将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;//交换这一段的位置
}
2.3 多轮加密
这里的设定是基于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);
}
}
3、加密示例
3.1 加密文本
这里对二进制文件进行加密示意。二进制文件的原始内容如下
加密解密代码如下:
#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)的情况下对数据进行还原是异常困难的。
3.2 加密图片
具体加密代码如下
#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个非重要函数并未公开。各位可以下载我的(付费资源)使用完整代码,或者自行根据以下代码提示补齐函数。
版权声明:本文标题:C++文件加密篇(基于char数组进行可逆加密) 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://m.elefans.com/dongtai/1729293094a1194417.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论