c++ openssl 使用 DES(数据加密标准)进行加密和解密的基本操作

news2025/6/6 17:42:29

使用 DES(数据加密标准)进行加密和解密的基本操作,重点展示了 ECB 和 CBC 模式,并且通过篡改密文的方式来进行攻击。下面是对每个部分的详细解析。

1. 结构体 Slip

struct Slip
{
    char from[16] = { 0 };  // 交易的发起者(例如 A => B)
    char to[16] = { 0 };    // 交易的接收者(例如 B => A)
    long long amount = 0;    // 交易金额
};
  • Slip 结构体存储了三部分数据:发起者 (from)、接收者 (to) 和交易金额 (amount)。
  • 这段数据需要加密并在后续的操作中进行篡改。

2. 全局变量:DES 密钥和密钥调度

static const_DES_cblock key = "1234567";
static DES_key_schedule key_sch;
  • key 是一个 8 字节的 DES 密钥,硬编码为 “1234567”。
  • key_sch 是 DES 密钥调度,它将密钥转换为 DES 算法可用的形式。

3. 加密函数 EnSlip

void EnSlip(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);
    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;
    }
}
  • EnSlip 负责对 Slip 数据进行加密。
  • 以 8 字节为单位处理 Slip 结构体的数据(DES 是块加密算法,每次处理 8 字节)。
  • DES_ecb_encrypt 用于在 ECB 模式下加密数据。
  • 每次加密后,将输入数据指针 p 和输出数据指针 o 移动 8 字节。

4. 解密函数 DeSlip

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;
    }
}
  • DeSlip 用于解密加密后的 Slip 数据。
  • 它与 EnSlip 类似,不过使用了 DES_DECRYPT 进行解密。

5. 篡改密文函数 AttackSlip

void AttackSlip(unsigned char* out)
{
    // 修改密文:交换 from 和 to
    unsigned char tmp[1024] = { 0 };
    memcpy(tmp, out, 16);            // 复制 from 部分
    memcpy(out, out + 16, 16);       // 将 to 部分放到 from 的位置
    memcpy(out + 16, tmp, 16);       // 将原来的 from 部分放到 to 的位置
}
  • AttackSlip 是一个简单的篡改密文的攻击方法,它交换了加密后的 from 和 to 字段。
  • 这种攻击显示了 ECB 模式的弱点,因为 ECB 模式在加密相同的数据块时会生成相同的密文,攻击者可以直接修改密文。

6. CBC 模式的加密函数 EnSlipCBC

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 };  // 初始化向量,设置为全零
    out_size = size;

    if (size % 8 != 0)
    {
        // 补充0到 8 的倍数
        out_size = size + (8 - size % 8);
    }
    DES_cbc_encrypt(p, o, sizeof(s), &key_sch, &iv, DES_ENCRYPT);
}
  • EnSlipCBC 使用 CBC 模式对 Slip 数据进行加密。
  • 如果数据长度不是 8 的倍数,则会填充零(补充到 8 字节的倍数)。
  • 使用 DES_cbc_encrypt 进行加密,其中需要提供初始化向量(IV)。在此处,IV 被初始化为全零。

7. CBC 模式的解密函数 DeSlipCBC

void DeSlipCBC(const unsigned char* in, int size, Slip& s)
{
    DES_cblock iv = { 0 };  // 初始化向量
    DES_set_key(&key, &key_sch);
    DES_cbc_encrypt(in, (unsigned char*)&s, size, &key_sch, &iv, DES_DECRYPT);
}
  • DeSlipCBC 用于解密 CBC 模式加密的数据。
  • 它使用与加密相同的 IV(此处为全零),并使用 DES_cbc_encrypt 解密数据。

8. 主函数 main

int main(int argc, char* argv[])
{
    unsigned char out[1024] = { 0 };
    int out_size = 0;
    Slip  s1 = { "USER_A", "USER_B", 10000 };
    cout << "s1 from:" << s1.from << endl;
    cout << "s1 to:" << s1.to << endl;
    cout << "s1 amount:" << s1.amount << endl;
    
    EnSlip(s1, out, out_size);
    cout << "En: " << out_size << " | " << out << endl;

    // 攻击密文
    AttackSlip(out);

    Slip s2;
    DeSlip(out, out_size, s2);
    cout << "s2 from:" << s2.from << endl;
    cout << "s2 to:" << s2.to << endl;
    cout << "s2 amount:" << s2.amount << endl;

    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 amount:" << s3.amount << endl;

    getchar();
    return 0;
}
  • 在主函数中,首先创建了一个交易数据 s1(发起者 “USER_A”、接收者 “USER_B”、金额 10000)。
  • 对 s1 使用 ECB 模式进行加密,并输出加密后的密文。
  • 然后,调用 AttackSlip 攻击密文,交换 from 和 to 字段,并解密密文。
  • 同样,对 s1 使用 CBC 模式进行加密,攻击密文后,再使用 CBC 解密。

9. 攻击分析

  • ECB 模式的漏洞: 因为 ECB 模式对每个数据块独立加密,导致相同的数据块加密后密文相同,攻击者可以直接修改密文(例如交换 from 和 to 字段),从而篡改交易数据。
  • CBC 模式的优势: 虽然 CBC 模式对每个数据块进行依赖加密,增强了安全性,但在此代码中并没有使用认证机制,攻击者仍然可以通过篡改密文的一部分(如改变密文中的块顺序)影响解密结果。

完整代码

#include <iostream>
#include <openssl/des.h>
#include <cstring>
using namespace std;

// 交易数据
struct Slip
{
    char from[16] = {0}; // A=>B 10000
    char to[16] = {0};   // 篡改为 B=>A 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)
{
    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            // 1 加密
        );
        p += 8;
        o += 8;
        out_size += 8;
    }
    // 补充数据。。。
}

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;
    }
}

void AttackSlip(unsigned char *out)
{
    // 修改密文 from 和to 对调
    unsigned char tmp[1024] = {0};
    // from
    memcpy(tmp, out, 16);
    // to copy from
    memcpy(out, out + 16, 16);
    memcpy(out + 16, tmp, 16);
}

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}; // 初始化向量
    out_size = size;
    // 数据如果不是8的倍数,会补0
    if (size % 8 != 0)
    {
        // 补充0
        out_size = size + (8 - size * 8);
    }
    DES_cbc_encrypt(
        p,         // 输入
        o,         // 输出
        sizeof(s), // 输入数据的大小
        &key_sch,  // 秘钥
        &iv,       // 初始化向量 DES_cbc_encrypt 调用后值不变
        // DES_ncbc_encrypt 保存上次的值
        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(int argc, char *argv[])
{
    unsigned char out[1024] = {0};
    int out_size = 0;
    Slip s1 = {"USER_A", "USER_B", 10000};
    cout << "s1 from:" << s1.from << endl;
    cout << "s1 to:" << s1.to << endl;
    cout << "s1 amount:" << s1.amount << endl;
    EnSlip(s1, out, out_size);
    cout << "En:" << out_size << "|" << out << endl;

    // 攻击密文
    AttackSlip(out);

    Slip s2;
    DeSlip(out, out_size, s2);
    cout << "s2 from:" << s2.from << endl;
    cout << "s2 to:" << s2.to << endl;
    cout << "s2 amount:" << s2.amount << endl;

    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 amount:" << s3.amount << endl;
    getchar();
    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2401932.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Git忽略规则.gitignore不生效解决

我在gitlab中新建了一个项目仓库&#xff0c;先把项目文件目录绑定到仓库&#xff0c;并全部文件都上传到了仓库中。 然后又从别的项目复制了忽略文件配置过来&#xff0c;怎么搞他都不能生效忽略我不要提交仓库的文件。 从网上查到说在本地仓库目录中&#xff0c;打开命…

6月5日day45

Tensorboard使用介绍 知识点回顾&#xff1a; tensorboard的发展历史和原理tensorboard的常见操作tensorboard在cifar上的实战&#xff1a;MLP和CNN模型 效果展示如下&#xff0c;很适合拿去组会汇报撑页数&#xff1a; 作业&#xff1a;对resnet18在cifar10上采用微调策略下&a…

基于rpc框架Dubbo实现的微服务转发实战

目录 rpc微服务模块 导入依赖 配置dubbo 注解 开启Dubbo Dubbo的使用 特殊点 并没有使用 Reference 注入 微服务之间调用 可以选用Http 也可以Dubbo 我们 Dubbo 的实现需要一个注册中心 我作为一个服务的提供者 我需要把我的服务注册到注册中心去 调用方需要注册中心…

深度学习N2周:构建词典

&#x1f368; 本文为&#x1f517;365天深度学习训练营中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 本周任务&#xff1a;使用N1周的.txt文件构建词典&#xff0c;停用词请自定义 1.导入数据 from torchtext.vocab import build_vocab_from_iterator from co…

贪心算法应用:装箱问题(FFD问题)详解

贪心算法应用&#xff1a;装箱问题(FFD问题)详解 1. 装箱问题概述 装箱问题(Bin Packing Problem)是计算机科学和运筹学中的一个经典组合优化问题。问题的描述如下&#xff1a; 给定一组物品&#xff0c;每个物品有一定的体积&#xff0c;以及若干容量相同的箱子&#xff0c…

操作系统学习(九)——存储系统

一、存储系统 在操作系统中&#xff0c;存储系统&#xff08;Storage System&#xff09; 是计算机系统的核心组成部分之一&#xff0c;它负责数据的存储、组织、管理和访问。 它不仅包括物理设备&#xff08;如内存、硬盘&#xff09;&#xff0c;还包括操作系统提供的逻辑抽…

服务器安装软件失败或缺依赖怎么办?

服务器在安装软件时失败或提示缺少依赖&#xff0c;是运维中非常常见的问题。这个问题大多发生在 Linux 云服务器环境&#xff0c;原因和解决方法也有共性。以下是详细说明和解决建议&#xff1a; &#x1f9e0; 一、常见原因分析 问题类型描述&#x1f50c; 软件源不可用服务器…

006网上订餐系统技术解析:打造高效便捷的餐饮服务平台

网上订餐系统技术解析&#xff1a;打造高效便捷的餐饮服务平台 在数字化生活方式普及的当下&#xff0c;网上订餐系统成为连接餐饮商家与消费者的重要桥梁。该系统以菜品分类、订单管理等模块为核心&#xff0c;通过前台展示与后台录入的分工协作&#xff0c;为管理员和会员提…

[10-2]MPU6050简介 江协科技学习笔记(22个知识点)

1 2 3 欧拉角是描述三维空间中刚体或坐标系之间相对旋转的一种方法。它们由三个角度组成&#xff0c;通常表示为&#xff1a; • 偏航角&#xff08;Yaw&#xff09;&#xff1a;绕垂直轴&#xff08;通常是z轴&#xff09;的旋转&#xff0c;表示偏航方向的变化。 • 俯仰角&a…

Spring Boot 3.X 下Redis缓存的尝试(二):自动注解实现自动化缓存操作

前言 上文我们做了在Spring Boot下对Redis的基本操作&#xff0c;如果频繁对Redis进行操作而写对应的方法显示使用注释更会更高效&#xff1b; 比如&#xff1a; 依之前操作对一个业务进行定入缓存需要把数据拉取到后再定入&#xff1b; 而今天我们可以通过注释的方式不需要额外…

【03】完整开发腾讯云播放器SDK的UniApp官方UTS插件——优雅草上架插件市场-卓伊凡

【03】完整开发腾讯云播放器SDK的UniApp官方UTS插件——优雅草上架插件市场-卓伊凡 一、项目背景与转型原因 1.1 原定计划的变更 本系列教程最初规划是开发即构美颜SDK的UTS插件&#xff0c;但由于甲方公司内部战略调整&#xff0c;原项目被迫中止。考虑到&#xff1a; 技术…

C:\Users\中文名修改为英文名

C:\Users\中文名修改为英文名 背景操作步骤 背景 买了台新电脑&#xff0c;初始化好不知道啥操作把自己的登录用户名改成了中文&#xff0c;有些安装的软件看见有中文直接就水土不服了。 操作步骤 以下称中文用户名为张三。 正常登录张三用户 进入用户管理页面修改用户名&a…

购物商城网站 Java+Vue.js+SpringBoot,包括商家管理、商品分类管理、商品管理、在线客服管理、购物订单模块

购物商城网站 JavaVue.jsSpringBoot&#xff0c;包括商家管理、商品分类管理、商品管理、在线客服管理、购物订单模块 百度云盘链接&#xff1a;https://pan.baidu.com/s/10W0kpwswDSmtbqYFsQmm5w 密码&#xff1a;68jy 摘 要 随着科学技术的飞速发展&#xff0c;各行各业都在…

在word中点击zotero Add/Edit Citation没有反应的解决办法

重新安装了word插件 1.关掉word 2.进入Zotero左上角编辑-引用 3.往下滑找到Microsoft Word&#xff0c;点重新安装加载项

整合swagger,以及Knife4j优化界面

因为是前后端项目&#xff0c;需要前端的参与&#xff0c;所以一个好看的接口文档非常的重要 1、引入依赖 美化插件其中自带swagger的依赖了 <dependency><groupId>com.github.xiaoymin</groupId><artifactId>knife4j-openapi3-spring-boot-starter&…

Unity | AmplifyShaderEditor插件基础(第四集:简易shader)

一、&#x1f44b;&#x1f3fb;前言 大家好&#xff0c;我是菌菌巧乐兹~本节内容主要讲一下&#xff0c;第一个用ASE的shader。 我们用通用的光照模版吧。&#xff08;universal-通用/Lit-光照&#xff09; 通用的光照模版 如果你尝试建设了&#xff0c;会发现Universal这个…

linux C语言中的动态库 静态库说明

静态库 gcc -fpic -c add.c sub.c 这个命令之后会得到 add.o 于 sub.o (-c 只编译不链接) ar rcs mymath.a add.o sub.o 将编译好的文件编译成.a静态库用于调用 在使用中 gcc main.c -I../include ../lib/mymarh.a -0 mytest 需要这个函数的声明放在include文件下&#xf…

Flash烧录速度和加载配置速度(纯FPGA ZYNQ)

在工程综合完成或者implement完成后&#xff0c;打开综合设计或者实现设计。 toots--->Edit Device Properties--->打开比特流设置 将bitstream进行压缩 上图中&#xff0c;时钟频率选择的档位有限&#xff0c;最大为66MHZ io的bus width可以设置为x1,x2,x4 vivado在设计…

解构与重构:PLM 系统如何从管理工具进化为创新操作系统?

在智能汽车、工业物联网等新兴领域的冲击下&#xff0c;传统产品生命周期管理&#xff08;PLM&#xff09;系统正在经历前所未有的范式转换。当某头部车企因 ECU 软件与硬件模具版本失配导致 10 万辆智能电车召回&#xff0c;损失高达 6 亿美元时&#xff0c;这场危机不仅暴露了…

Redis:介绍和认识,通用命令,数据类型和内部编码,单线程模型

介绍和认识 Redis是一个基于内存的&#xff0c;高性能的&#xff0c;支持许多数据类型的NoSQL数据库&#xff0c;可以持久化&#xff0c;也支持分布式。 在许多的互联网产品中&#xff0c;对于数据库的访问速度要求很高&#xff0c;例如Mysql数据库无法满足其要求&#xff0c…