Loading...      - 对称分组加密常用算法: ·DES ·3DES ·AES ·国密SM4 - 对称分组加密应用场景: 文件或者视频加密 加密比特币私钥 消息或者配置项加密 SSL通信加密 # 对称分组加密 ## 使用异或实现一个简易的对称加密算法 A明文 B秘钥 A^B=密文A^B (A^B)^B =A > 密码补全和初始化 > 数据补全策略:PADDING_PKCS7(补其他) PADDING_ZERO(补0) > > 举例: > > block = 8 > > 12345678 9 > 12345678 90000000 ZERO > > 12345678 97777777 PKCS7 > > 更详细请看:[DES加密初探 - 乙太的小屋 (52ying.top)](https://www.oisec.cn/index.php/archives/934/)DES算法填充方式 ``` #include <iostream> using namespace std; //对称加解密数据 //@para data 输入数据 //@para data_size 输入数据大小 //@para out 输出数据 //@para pass 密钥 //@para pass_size 密钥长度 //@return 加解密后数据大小 #define XOR_BLOCK 8 int XorCipher(const unsigned char* data, int data_size, unsigned char* out, const unsigned char* pass, int pass_size ) { static const char iv[] = "abcdefgt"; //初始化密钥 auto p = *(unsigned long long*)iv; //密钥补全,并且异或初始化向量 //密钥小于XOR_BLOCK或者大于XOR_BLOCK for (int i = 0; i < pass_size; i += XOR_BLOCK) { unsigned long long tmp = 0; int size = XOR_BLOCK; //密钥小于 XOR_BLOCK if (pass_size - i < XOR_BLOCK) { size = pass_size - i; } memcpy(&tmp, (pass + i), size); p = (p ^ tmp); } //数据源转换成8字节数据类型 auto d = (unsigned long long*)data; //输出数据 auto o = (unsigned long long*)out; //数据分组处理 int i = 0; for (; i < data_size / XOR_BLOCK; i++) { o[i] = (d[i] ^ p); } //输入数据的补充 int mod = data_size % XOR_BLOCK; if (mod != 0) { unsigned long long tmp = 0; memcpy(&tmp, (d + i), mod); } int re_size = data_size; return re_size; } int main1(int argc, char* argv[]) { unsigned char data[] = "测试加解密数据TEST123测试"; unsigned char out[1024] = { 0 }; unsigned char out2[1024] = { 0 }; unsigned char pass[] = "12345678"; int pass_size = strlen((char*)pass); int len = XorCipher(data, sizeof(data),out, pass, pass_size); cout << len << "|"<<out << endl; len = XorCipher(out, len, out2, pass, pass_size); cout << len << "|" << out2 << endl; return 0; } ``` ## DES_ECB攻击 ``` #include <iostream> #include <openssl/des.h> using namespace std; //交易数据 struct Slip { char from[16] = { 0 }; //A=>B 10000 char to[16] = { 0 }; //篡改为B=> 10000 long long amount = 0; }; static const_DES_cblock key = "1234567"; static DES_key_schedule key_sch; void EnSlip(const Slip& s, unsigned char* out, int& out_size) { const int size = sizeof(s); auto p = (const unsigned char*)&s; auto o = out; DES_set_key(&key, &key_sch); for(int i = 0; i < size; i += 8) { DES_ecb_encrypt((const_DES_cblock*)p, (DES_cblock*)o, &key_sch, DES_ENCRYPT); p += 8; o += 8; out_size += 8; } } void AttackSlip(unsigned char* out) { //修改秘文的from和to对调 unsigned char tmp[1024] = { 0 }; //from memcpy(tmp, out, 16); memcpy(out, out + 16, 16); memcpy(out + 16, tmp, 16); } void DeSlip(const unsigned char* in, int size, Slip& s) { auto p = (const unsigned char*)in; auto o = (unsigned char*)&s; DES_set_key(&key, &key_sch); for (int i = 0; i < size; i += 8) { DES_ecb_encrypt((const_DES_cblock*)p, (DES_cblock*)o, &key_sch, DES_DECRYPT); p += 8; o += 8; } } int main() { { unsigned char out[1024] = { 0 }; int out_size = 0; Slip s1 = { "USER_A","USER_B",10000 }; cout << "s2 from: " << s1.from << endl; cout << "s2 to: " << s1.to << endl; cout << "s2 ammout: " << s1.amount << endl; EnSlip(s1, out, out_size); cout << "En:"<< out_size <<"---->" << out << endl; //攻击密文1 AttackSlip(out); Slip s2; DeSlip(out, out_size, s2); cout << "s2 from: " << s2.from << endl; cout << "s2 to: " << s2.to << endl; cout << "s2 ammout: " << s2.amount << endl; } unsigned char data[] = "1234567";//数据 unsigned char out[1024] = { 0 };//输出数据 unsigned char out2[1024] = { 0 }; //1.设置密钥 DES_set_key(&key, &key_sch); //数据加密 DES_ecb_encrypt((const_DES_cblock*)data, (DES_cblock*)out, &key_sch, DES_ENCRYPT); cout << "加密:" << out << endl; //解密 DES_ecb_encrypt((const_DES_cblock*)out, (DES_cblock*)out2, &key_sch, DES_DECRYPT); cout << "解密:" << out2 << endl; getchar(); return 0; } ``` #### DES_CBC ``` void EnSlipCBC(const Slip& s, unsigned char* out, int& out_size) { int size = sizeof(s); auto p = (const unsigned char*)&s; auto o = out; DES_set_key(&key, &key_sch); DES_cblock iv = { 0 };//初始化向量 //初始化向量 DES_cbc_encrypt 调用后值不变 DES_ncbc_encrypt保存上次的值 //如果数据不是8的倍数,会自动补0 if (size % 8!= 0) { out_size = size + (8 - size % 8); } DES_cbc_encrypt(p, o, sizeof(s), &key_sch, &iv,DES_ENCRYPT); } void DeSlipCBC(const unsigned char* in, int size, Slip& s) { DES_cblock iv = { 0 }; DES_set_key(&key, &key_sch); //如果补0了,解密后无法知道实际大小,需要用户存储原数据大小 DES_cbc_encrypt(in, (unsigned char*)&s, size, &key_sch, &iv, DES_DECRYPT); } int main() { Slip s3; EnSlipCBC(s1, out, out_size); //AttackSlip(out); DeSlipCBC(out, out_size, s3); cout << "s3 from: " << s3.from << endl; cout << "s3 to: " << s3.to << endl; cout << "s3 ammout: " << s3.amount << endl; } ``` # 封装DES实现CBC和ECB的PKCS7Padding分块填充 ``` #pragma once #include <string> #include <openssl/des.h> //枚举类型 enum XSecType { XDES_ECB, XDES_CBC }; /* Xsec sec; sec.Init(XDES_ECB,"12345678",ture); */ class XSec { public: /// 初始化加密对象 /// <param name="type">加密类型</param> /// <param name="pass">密钥,可以是二进制</param> /// <param name="is_en">true加密,false解密</param> /// 是否成功 virtual bool Init(XSecType type, const std::string& pass, bool is_en); /// <summary> /// 加解密数据 /// </summary> /// <param name="in">输入数据</param> /// <param name="in_size">数据大小</param> /// <param name="out">输出数据</param> /// <returns>成功返回加解密后数据大小,失败返回0</returns> virtual int Encrypt(const unsigned char* in, int in_size, unsigned char* out); private: /// <summary> ///DES_ECB加密模式 /// </summary> int EnDesECB(const unsigned char* in, int in_size, unsigned char* out); //DES_ECB解密模式 int DeDesECB(const unsigned char* in, int in_size, unsigned char* out); ///DES_CBC加密模式 /// </summary> int EnDesCBC(const unsigned char* in, int in_size, unsigned char* out); //DES_CBC解密模式 int DeDesCBC(const unsigned char* in, int in_size, unsigned char* out); //加密算法密钥 DES_key_schedule ks_; //加秘算法类型 XSecType type_; bool is_en_; //数据块分组大小 int block_size_ = 0; //初始化向量 unsigned char iv_[128] = { 0 }; }; ``` --- ``` #include "xsec.h" #include <iostream> using namespace std; bool XSec::Init(XSecType type, const std::string& pass, bool is_en) { this->type_ = type; this->is_en_ = is_en; this->block_size_ = DES_KEY_SZ; //初始化iv_ memset(iv_, 0, sizeof(iv_)); const_DES_cblock key = { 0 }; //密码策略,超出8字节丢弃,少的补充0 int key_size = pass.size(); if (key_size > block_size_) key_size = block_size_; memcpy(&key, pass.data(), key_size); DES_set_key(&key, &ks_); return true; } int XSec::Encrypt(const unsigned char* in, int in_size, unsigned char* out) { if(type_ == XDES_ECB) if (is_en_) { return EnDesECB(in, in_size, out); } else { return DeDesECB(in, in_size, out); } else if (type_ == XDES_CBC) if (is_en_) { return EnDesCBC(in, in_size, out); } else { return DeDesCBC(in, in_size, out); } return 0; } int XSec::EnDesECB(const unsigned char* in, int in_size, unsigned char* out) { //数据填充PKCS7 Padding //PKCS7Padding:假设数据长度需要填充n(n>0)个字节才对齐,那么填充n个字节,每个字节都是n;如果数据本身就已经对齐了,则填充一块长度为块大小的数据,每个字节都是块大小。 unsigned char padding[8] = { 0 }; int padding_size = block_size_ - (in_size % block_size_); //填入补充的字节大小 memset(padding, padding_size, sizeof(padding)); int i = 0; for ( ; i < in_size; i += block_size_) { //最后一块数据,小于block_size_ 需要填充 if ( in_size-i<block_size_) { //填入数据 memcpy(padding, in + i, in_size - i); break; } DES_ecb_encrypt((const_DES_cblock*)(in + i), (DES_cblock*)(out + i), &ks_, DES_ENCRYPT); } //补充 PKCS7结尾 DES_ecb_encrypt((const_DES_cblock*)padding, (DES_cblock*)(out + i), &ks_, DES_ENCRYPT); return in_size + padding_size; } int XSec::DeDesECB(const unsigned char* in, int in_size, unsigned char* out) { for (int i = 0; i < in_size; i += block_size_) { DES_ecb_encrypt((const_DES_cblock*)(in + i), (DES_cblock*)(out + i), &ks_, DES_DECRYPT); } return in_size - out[in_size - 1]; } int XSec::EnDesCBC(const unsigned char* in, int in_size, unsigned char* out) { //数据填充PKCS7 Padding unsigned char padding[8] = { 0 }; int padding_size = block_size_ - (in_size % block_size_); //填入补充的字节大小 memset(padding, padding_size, sizeof(padding)); //ncbc保留iv修改 减去需要补充的数据 DES_ncbc_encrypt(in, out, in_size - (in_size % block_size_),&ks_,(DES_cblock*)iv_,DES_ENCRYPT); //PKCS7 Padding if (in_size % block_size_ != 0) { memcpy(padding, in + (in_size - (in_size % block_size_)), in_size % block_size_); } DES_ncbc_encrypt(padding, out+(in_size - (in_size % block_size_)),sizeof(padding), &ks_, (DES_cblock*)iv_, DES_ENCRYPT); return in_size+padding_size; } int XSec::DeDesCBC(const unsigned char* in, int in_size, unsigned char* out) { DES_ncbc_encrypt(in, out, in_size, &ks_, (DES_cblock*)iv_, DES_DECRYPT); return in_size - out[in_size-1]; } int main(int argc, char* argv[]) { { unsigned char data[] = "123456789"; unsigned char out[1024] = { 0 }; unsigned char out2[1024] = { 0 }; XSec sec; //ECB加密 sec.Init(XDES_ECB, "12345678", true); cout <<"============== DES_ECB==================" << endl; cout << sizeof(data) << "[" << data << "]" << endl; int size = sec.Encrypt(data, sizeof(data), out); cout << size << ":" << out << endl; //ECB解密 sec.Init(XDES_ECB, "12345678", false); size = sec.Encrypt(out, size, out2); cout << size << "[" << out2 << "]" << endl; //CBC解密 sec.Init(XDES_CBC, "12345678", true); cout << "============== DES_CBC==================" << endl; cout << sizeof(data) << "[" << data << "]" << endl; size = sec.Encrypt(data, sizeof(data), out); cout << size << ":" << out << endl; //CBC解密 sec.Init(XDES_CBC, "12345678", false); size = sec.Encrypt(out, size, out2); cout << size << "[" << out2 << "]" << endl; getchar(); } } ``` 最后修改:2023 年 11 月 10 日 © 允许规范转载 打赏 赞赏作者 支付宝微信 赞 1 如果觉得我的文章对你有用,请随意赞赏
1 条评论
果博东方客服开户联系方式【182-8836-2750—】?薇- cxs20250806】
果博东方公司客服电话联系方式【182-8836-2750—】?薇- cxs20250806】
果博东方开户流程【182-8836-2750—】?薇- cxs20250806】
果博东方客服怎么联系【182-8836-2750—】?薇- cxs20250806】