2023/11/10学习记录-C/C++对称分组加密DES

简介: 本文介绍了对称分组加密的常见算法(如DES、3DES、AES和国密SM4)及其应用场景,包括文件和视频加密、比特币私钥加密、消息和配置项加密及SSL通信加密。文章还详细展示了如何使用异或实现一个简易的对称加密算法,并通过示例代码演示了DES算法在ECB和CBC模式下的加密和解密过程,以及如何封装DES实现CBC和ECB的PKCS7Padding分块填充。

image.png

image.png

image.png

image.png

image.png

  • 对称分组加密常用算法:

·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)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

using namespace std;

bool XSec::Init(XSecType type, const std::string& pass, bool isen)
{
this->type
= type;
this->isen = is_en;
this->blocksize = DES_KEYSZ;
//初始化iv

memset(iv, 0, sizeof(iv));
const_DES_cblock key = { 0 };
//密码策略,超出8字节丢弃,少的补充0
int key_size = pass.size();
if (key_size > blocksize) key_size = blocksize;
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 (isen)
{
return EnDesECB(in, in_size, out);
}
else {
return DeDesECB(in, insize, out);
}
else if (type
== XDES_CBC)
if (isen)
{
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 = blocksize - (in_size % blocksize);
//填入补充的字节大小
memset(padding, padding_size, sizeof(padding));
int i = 0;
for ( ; i < in_size; i += blocksize)
{
//最后一块数据,小于blocksize 需要填充
if ( in_size-i<blocksize)
{
//填入数据
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 += blocksize)
{
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 = blocksize - (in_size % blocksize);
//填入补充的字节大小
memset(padding, padding_size, sizeof(padding));
//ncbc保留iv修改 减去需要补充的数据
DES_ncbc_encrypt(in, out, in_size - (in_size % blocksize),&ks_,(DEScblock*)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, insize, &ks, (DEScblock*)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();
}

}

相关文章
|
6天前
|
存储 运维 安全
云上金融量化策略回测方案与最佳实践
2024年11月29日,阿里云在上海举办金融量化策略回测Workshop,汇聚多位行业专家,围绕量化投资的最佳实践、数据隐私安全、量化策略回测方案等议题进行深入探讨。活动特别设计了动手实践环节,帮助参会者亲身体验阿里云产品功能,涵盖EHPC量化回测和Argo Workflows量化回测两大主题,旨在提升量化投研效率与安全性。
云上金融量化策略回测方案与最佳实践
|
8天前
|
人工智能 自然语言处理 前端开发
从0开始打造一款APP:前端+搭建本机服务,定制暖冬卫衣先到先得
通义灵码携手科技博主@玺哥超carry 打造全网第一个完整的、面向普通人的自然语言编程教程。完全使用 AI,再配合简单易懂的方法,只要你会打字,就能真正做出一个完整的应用。
8214 19
|
12天前
|
Cloud Native Apache 流计算
资料合集|Flink Forward Asia 2024 上海站
Apache Flink 年度技术盛会聚焦“回顾过去,展望未来”,涵盖流式湖仓、流批一体、Data+AI 等八大核心议题,近百家厂商参与,深入探讨前沿技术发展。小松鼠为大家整理了 FFA 2024 演讲 PPT ,可在线阅读和下载。
4437 10
资料合集|Flink Forward Asia 2024 上海站
|
20天前
|
人工智能 自动驾驶 大数据
预告 | 阿里云邀您参加2024中国生成式AI大会上海站,马上报名
大会以“智能跃进 创造无限”为主题,设置主会场峰会、分会场研讨会及展览区,聚焦大模型、AI Infra等热点议题。阿里云智算集群产品解决方案负责人丛培岩将出席并发表《高性能智算集群设计思考与实践》主题演讲。观众报名现已开放。
|
12天前
|
自然语言处理 数据可视化 API
Qwen系列模型+GraphRAG/LightRAG/Kotaemon从0开始构建中医方剂大模型知识图谱问答
本文详细记录了作者在短时间内尝试构建中医药知识图谱的过程,涵盖了GraphRAG、LightRAG和Kotaemon三种图RAG架构的对比与应用。通过实际操作,作者不仅展示了如何利用这些工具构建知识图谱,还指出了每种工具的优势和局限性。尽管初步构建的知识图谱在数据处理、实体识别和关系抽取等方面存在不足,但为后续的优化和改进提供了宝贵的经验和方向。此外,文章强调了知识图谱构建不仅仅是技术问题,还需要深入整合领域知识和满足用户需求,体现了跨学科合作的重要性。
|
8天前
|
人工智能 容器
三句话开发一个刮刮乐小游戏!暖ta一整个冬天!
本文介绍了如何利用千问开发一款情侣刮刮乐小游戏,通过三步简单指令实现从单个功能到整体框架,再到多端优化的过程,旨在为生活增添乐趣,促进情感交流。在线体验地址已提供,鼓励读者动手尝试,探索编程与AI结合的无限可能。
三句话开发一个刮刮乐小游戏!暖ta一整个冬天!
|
1月前
|
存储 人工智能 弹性计算
阿里云弹性计算_加速计算专场精华概览 | 2024云栖大会回顾
2024年9月19-21日,2024云栖大会在杭州云栖小镇举行,阿里云智能集团资深技术专家、异构计算产品技术负责人王超等多位产品、技术专家,共同带来了题为《AI Infra的前沿技术与应用实践》的专场session。本次专场重点介绍了阿里云AI Infra 产品架构与技术能力,及用户如何使用阿里云灵骏产品进行AI大模型开发、训练和应用。围绕当下大模型训练和推理的技术难点,专家们分享了如何在阿里云上实现稳定、高效、经济的大模型训练,并通过多个客户案例展示了云上大模型训练的显著优势。
104585 10
|
7天前
|
消息中间件 人工智能 运维
12月更文特别场——寻找用云高手,分享云&AI实践
我们寻找你,用云高手,欢迎分享你的真知灼见!
650 40
|
5天前
|
弹性计算 运维 监控
阿里云云服务诊断工具:合作伙伴架构师的深度洞察与优化建议
作为阿里云的合作伙伴架构师,我深入体验了其云服务诊断工具,该工具通过实时监控与历史趋势分析,自动化检查并提供详细的诊断报告,极大提升了运维效率和系统稳定性,特别在处理ECS实例资源不可用等问题时表现突出。此外,它支持预防性维护,帮助识别潜在问题,减少业务中断。尽管如此,仍建议增强诊断效能、扩大云产品覆盖范围、提供自定义诊断选项、加强教育与培训资源、集成第三方工具,以进一步提升用户体验。
633 243
|
2天前
|
弹性计算 运维 监控
云服务测评 | 基于云服务诊断全方位监管云产品
本文介绍了阿里云的云服务诊断功能,包括健康状态和诊断两大核心功能。作者通过个人账号体验了该服务,指出其在监控云资源状态和快速排查异常方面的优势,同时也提出了一些改进建议,如增加告警配置入口和扩大诊断范围等。