Qt实现DES ECB加密解密

news2024/11/24 23:21:02

环境:Windows11 64位
工具链:MinGW32
IDE:Qt 5.14

Qt使用DES加密需要用到OpenSSL库,首先要确定当前使用的Qt所支持的SSL版本。

编译OpenSSL

查看当前Qt对OpenSSL的支持情况

qDebug() << QSslSocket::supportsSsl();

返回 true 则表示系统支持OpenSSL,返回 false 表示系统不支持OpenSSL。

查看Qt所支持的OpenSSL版本

OpenSSL在版本兼容性问题上是出了名的,所以必须要搞清楚自己所用Qt版本所支持的OpenSSL版本。用如下代码进行OpenSSL版本查看:

 qDebug() << QSslSocket::sslLibraryBuildVersionString();

下载对应版本的OpenSSL

根据自己操作系统的种类以及位数,下载对应的OpenSSL版本,下载地址如下:

OpenSSL官网下载地址

编译源码

本篇文章主要讲解的是MinGW编译方法,需要用到msys2。

下载安装msys2

推荐使用清华的镜像网站下载,速度快。
官网网址(不推荐)
清华镜像(推荐)
选择一个版本下载,我选择的是20220503的版本。
在这里插入图片描述
下载源码后将源码解压到 msys\home\用户名\路径下。

更改msys2的下载源

刚下载的msys2使用的默认源在国外,所以下载东西非常慢,需要自己更改成国内的源。

  1. 打开安装目录下的 \etc\pacman.d 可以看到下图中红框中的三个文件
    在这里插入图片描述
  2. 用记事本打开 mirrorlist.msys ,在文本的最上面加上这句代码
Server = https://mirrors.tuna.tsinghua.edu.cn/msys2/msys/$arch
  1. 同理使用记事本打开 mirrorlist.mingw32 ,在最上面增加
Server = https://mirrors.tuna.tsinghua.edu.cn/msys2/mingw/i686
  1. 修改 mirrorlist.mingw64 ,同理在最上面增加
Server = https://mirrors.tuna.tsinghua.edu.cn/msys2/mingw/x86_64
  1. 在安装路径下找到msys.exe打开,执行下面指令更新
pacman -Syu

配置msys2的MinGW环境

我需要编译的是32位的OpenSSL,需要安装mingw32的环境。

  1. 在安装目录下打开mingw32.exe。
  2. 打开后先用pacman -Syu指令,更新一下下载列表(防止还是用旧的源)。
  3. 下载C++编译所需文件。
pacman -S mingw-w64-i686-toolchain
  1. 安装gcc
pacman -S gcc
  1. 安装make
pacman -S make

编译源码生成动态库

  1. 进入openssl的文件夹
cd openssl-1.1.1d/
  1. 配置编译环境
./config -shared
  1. 编译(等待个几分钟)
make

编译过程中会有很多警告,无视即可,然后在\openssl-1.1.1d\test就能找到两个动态库(libcrypto-1_1.dll和libssl-1_1.dll)。

使用Qt调用OpenSSL

新建测试项目

  1. 在源码路径下新建libs和openssl文件夹
  2. 复制libcrypto-1_1.dl和libssl-1_1.dll到libs文件夹下
  3. 复制openssl-1.1.1k/include目录到openssl文件夹下

配置工程.pro文件

  1. 添加引用库
LIBS += -L$$PWD/libs/ -llibcrypto-1_1 -llibssl-1_1
  1. 添加头文件路径
INCLUDEPATH += $$PWD/openssl/include

编写代码

我测试的是DES ECB方式解密解密,需要引用相应的头文件

#include "openssl/des.h"
// 加密函数
// 加密 ecb模式
QByteArray DesEcb::des_encrypt(const std::string &clearText, const std::string &key)
{
    // DES加密分为两个阶段
    // 第一阶段是设置密钥,从密钥生成DES_key_schedule
    // 第二阶段是实际加密

    std::string cipherText; // 密文

    // 第一阶段,设置密钥
    // DES的密钥类型是DES_cblock,8位
    DES_cblock keyEncrypt;
    memset(keyEncrypt, 0, 8);
    // 构造补齐后的密钥
    if(key.length() <= 8)
        memcpy(keyEncrypt, key.c_str(), key.length());
    else
        memcpy(keyEncrypt, key.c_str(), 8);

    // 密钥置换
    DES_key_schedule keySchedule;
    DES_set_key_unchecked(&keyEncrypt, &keySchedule);
    //DES_set_key_checked(&keyEncrypt, &keySchedule);

    // 第二阶段,实际加密
    // 循环加密,每8字节一次
    const_DES_cblock inputText; // 加密前的输入8字节
    DES_cblock outputText; // 加密后的输出
    std::vector<unsigned char> vecCiphertext;  // 加密后的密文
    unsigned char tmp[8]; // 记录加密过程中的数据块的数据

    for(int i = 0; i < clearText.length() / 8; i++) {
        memcpy(inputText, clearText.c_str() + i * 8, 8);
        DES_ecb_encrypt(&inputText, &outputText, &keySchedule, DES_ENCRYPT);
        memcpy(tmp, outputText, 8);

        for(int j = 0; j < 8; j++)
            vecCiphertext.push_back(tmp[j]);
    }

    // PkCs5padding填充模式
    // 数据块大小固定为8数据长度
    // 需要填充n(n>0)个字节才对齐,那么填充n个字节,每个字节都是n
    // 如果数据本身就已经对齐了,则填充一块长度为块大小的数据,每个字节都是块大小8
    if(clearText.length() % 8 == 0) {
        //PkCs5padding
        memset(inputText, 8, 8);
        // 加密函数
        DES_ecb_encrypt(&inputText, &outputText, &keySchedule, DES_ENCRYPT);
        memcpy(tmp, outputText, 8);

        for(int j = 0; j < 8; j++)
            vecCiphertext.push_back(tmp[j]);
    }

    if(clearText.length() % 8 != 0) {
        // PkCs5padding
        int tmp1 = clearText.length() / 8 * 8;
        int tmp2 = clearText.length() - tmp1;
        int padNumber = 8 - tmp2;//最后一个需要补齐的数据块需要补齐的位数
        memset(inputText, padNumber, 8);
        memcpy(inputText, clearText.c_str() + tmp1, tmp2); //最后一个补齐的数据块
        // 加密函数
        DES_ecb_encrypt(&inputText, &outputText, &keySchedule, DES_ENCRYPT); //DES_ENCRYPT代表加密
        memcpy(tmp, outputText, 8);

        for(int j = 0; j < 8; j++)
            vecCiphertext.push_back(tmp[j]);
    }

    cipherText.clear();
    cipherText.assign(vecCiphertext.begin(), vecCiphertext.end());

    QByteArray tempArray;
    foreach (auto var, vecCiphertext) {
        tempArray.append(var);
    }

    return tempArray;
}


// 解密
std::string DesEcb::des_decrypt(const std::string &cipherText, const std::string &key)
{
    std::string clearText; // 明文

    DES_cblock keyEncrypt;
    memset(keyEncrypt, 0, 8);

    if(key.length() <= 8)
        memcpy(keyEncrypt, key.c_str(), key.length());
    else
        memcpy(keyEncrypt, key.c_str(), 8);

    DES_key_schedule keySchedule;
    DES_set_key_unchecked(&keyEncrypt, &keySchedule);

    const_DES_cblock inputText;
    DES_cblock outputText;
    std::vector<unsigned char> vecCleartext;
    unsigned char tmp[8];

    for(int i = 0; i < cipherText.length() / 8; i++) {
        memcpy(inputText, cipherText.c_str() + i * 8, 8);
        DES_ecb_encrypt(&inputText, &outputText, &keySchedule, DES_DECRYPT);  //DES_DECRYPT代表解密
        memcpy(tmp, outputText, 8);

        for (int j = 0; j < 8; j++) {
            if(tmp[j] > 31) //31是什么意思???????????????????
                vecCleartext.push_back(tmp[j]);
        }
    }

    if(cipherText.length() % 8 != 0) {
        int tmp1 = cipherText.length() / 8 * 8;
        int tmp2 = cipherText.length() - tmp1;
        memset(inputText, 0, 8);
        memcpy(inputText, cipherText.c_str() + tmp1, tmp2);
        // 解密函数
        DES_ecb_encrypt(&inputText, &outputText, &keySchedule, DES_DECRYPT);
        memcpy(tmp, outputText, 8);

        for(int j = 0; j < 8; j++)
            vecCleartext.push_back(tmp[j]);
    }

    clearText.clear();
    clearText.assign(vecCleartext.begin(), vecCleartext.end());

    return clearText;
}

在这里插入图片描述

附:项目源码

参考链接:

  1. https://blog.csdn.net/l1206715877/article/details/125120888
  2. https://blog.csdn.net/YinShiJiaW/article/details/106220932
  3. https://www.cnblogs.com/rockyching2009/p/14989873.html
  4. https://www.codenong.com/cs106278466/

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

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

相关文章

C++STL简介

本期我们来简单介绍一下STL 目录 1.什么是STL 2.STL的版本 3.STL的六大组件 4.如何学习STL 5.STL的缺陷 本期内容比较简单&#xff0c;大家只需简单看看了解一下即可 1.什么是STL STL(standard template libaray- 标准模板库 ) &#xff1a; 是 C 标准库的重要组成部分 &…

Postman使用技巧

本文仅针对笔者的Postman使用习惯&#xff0c;纯属个人理解&#xff0c;如有不同或更好的方式烦请指出。 文章目录 前言一、Postman是什么&#xff1f;二、使用步骤1. Collection分级习惯2.配置环境变量3.Postman接口请求自带url前缀3.1 方式一&#xff1a;在url中添加环境变量…

深度学习框架搭建

5.15 首先是了解下&#xff0c;怎么配置环境啊这一套的。。 1.大概了解了一些名词意思 python&#xff0c;不用说了&#xff0c;就是一门语言 anoconda是一些包啊之类的管理工具&#xff0c;挺好用的&#xff0c;管理虚拟环境用的。 jupyter和pycharm都是类似于IDE吧&#…

【系统移植】SD卡烧录uboot、linux内核、根文件系统

目录 一、SD卡分区 二、SD卡烧录uboot 三、SD卡烧录linux内核 四、SD卡烧录根文件系统 五、修改uboot环境变量 1、设置 bootcmd 2、设置 bootargs 参考链接&#xff1a;IMX6Q的SD卡启动使用教程_mayue_csdn的博客-CSDN博客 一、SD卡分区 无论是EMMC还是SD卡启动&#…

Promise理解

做一道题,理解一下: function getPrinterList() {let res 初始setTimeout(() > {res 1},1000)return res }let res getPrinterList() console.log(res); //输出初始 在getPrinterList函数中,先分清同步异步. JS执行语句时,会区分同步异步,把所有的同步放在同步队列中,把…

2023-5-19-Debug和Release到底有多少不同?

&#x1f37f;*★,*:.☆(&#xffe3;▽&#xffe3;)/$:*.★* &#x1f37f; &#x1f4a5;&#x1f4a5;&#x1f4a5;欢迎来到&#x1f91e;汤姆&#x1f91e;的csdn博文&#x1f4a5;&#x1f4a5;&#x1f4a5; &#x1f49f;&#x1f49f;喜欢的朋友可以关注一下&#xf…

【HTTPS加密】

&#x1f389;&#x1f389;&#x1f389;点进来你就是我的人了博主主页&#xff1a;&#x1f648;&#x1f648;&#x1f648;戳一戳,欢迎大佬指点! 欢迎志同道合的朋友一起加油喔&#x1f93a;&#x1f93a;&#x1f93a; 目录 1.HTTPS 是什么 1.1 运营商劫持 1.2 关于加密…

面试季,真的太狠了...

金三银四面试季的复盘&#xff0c;真的太狠了… 面试感受 先说一个字 是真的 “ 累 ” 安排的太满的后果可能就是一天只吃一顿饭&#xff0c;一直奔波在路上 不扯这个了&#xff0c;给大家说说面试吧&#xff0c;我工作大概两年多的时间&#xff0c;大家可以参考下 在整个面…

【FMC201】基于FMC标准的1路CameraLink Full 输入 子卡模块

产品概述 FMC201是一款CameraLink信号输入&#xff08;采集&#xff09;FMC子卡模块&#xff0c;该模块支持2路CameraLink Base模式或者1路CameraLink Full模式的图像信号输入。板卡具有2个CameraLink端口&#xff08;SDR26&#xff09;&#xff0c;可以作为采集卡使用。 技术指…

不仅能满足需求,还能提高效率。教你建立自动化测试请求封装

目录 前言&#xff1a; 一、整体框架介绍 二、代码实现 1. config文件配置 2. API封装方法实现 3. 测试用例编写 4. 运行测试用例 三、总结 前言&#xff1a; 在接口自动化测试中&#xff0c;我们都知道一个重要概念就是接口请求封装&#xff0c;可以大幅度提供自动化…

中间件(三)- Zookeeper

Zookeeper 1. Zookeeper介绍1.1 什么是Zookeeper1.2 Zookeeper的应用场景 2. 搭建ZooKeeper服务器2.1 下载安装包2.2 配置文件2.3 启动测试 3. Zookeeper内部的数据模型3.1 zk如何保存数据?3.2 zk中的znode是什么样的数据结构3.3 zk中节点znode的类型3.4 zk的数据持久化 4. Zo…

18-01 数据库架构设计综述

数据库架构设计的基本思路 需求分析阶段&#xff08;最困难、最耗时&#xff09; 整个设计过程的基础 需求分析做得是否充分以及准确&#xff0c;决定了数据库设计的速度与质量极端场景下&#xff0c;需求分析做得不好&#xff0c;可能会导致整个数据库设计返工、重做 需求分…

RSBBS 报表接口 query跳转 RRI

这里只讲RSBBS的goto query&#xff0c;不讲query里面的替换路径。 报表接口就是从一个query跳转到另一个目的地。从下面能看到&#xff0c;可以跳转到一个BW系统下的query&#xff0c;或者能跳转到ERP系统的一个ABAP report也行&#xff0c;或者可以通过archive link去从quer…

node之excel转化成json格式的数据

1. node环境(自己看教程搭建) 2.安装node-xlsx和fs yarn node-xlsx 3.写代码。简单实例如下&#xff08;如果需要处理数据&#xff0c;自己处理&#xff09; 实例&#xff1a; 目录&#xff1a; b.js var xlsx require(node-xlsx); var fs require(fs); const path requ…

基于布谷鸟优化算法(CS)在微电网优化中的应用研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

【Mybatis】SpringBoot整合Mybatis之增删改查

目录 一、准备 1、选择依赖 2、配置文件 3、映射接口 二、Select 三、Delete 四、Update 五、Insert 一、准备 1、选择依赖 在我们创建SpringBoot项目的时候&#xff0c;需要选择Mybatis与MySQL的依赖 2、配置文件 然后我们需要在配置文件里配置MySQL的连接信息 spr…

UEBA技术在ADAudit Plus中的应用

摘要&#xff1a;用户和实体行为分析&#xff08;UEBA&#xff09;技术是当今信息安全领域的重要工具之一。本文将介绍UEBA技术在ADAudit Plus中的应用&#xff0c;探讨其在提供安全性和监控能力方面的优势&#xff0c;并解释为何ADAudit Plus是一种出色的UEBA解决方案。 UEBA …

免费下载|《建设数字中国 升级数智底座-企业数智化底座白皮书》

企业数智化历经多年的演进&#xff0c;已经从最初的“局部推动业务提质增效”&#xff0c;发展为“利用技术全面赋能业务创新活动”&#xff0c;数智化能力的建设正逐步与企业的战略目标深度融合。企业践行数字化优先&#xff0c;以智能化促进发展&#xff0c;根本上需要依托健…

高并发系统的三把利器

目录 1.限流 2.缓存 2.1.缓存的使用场景 3.降级 3.1.什么是降级&#xff1f; 3.2.服务降级方式 4.其他高并发手段 4.1. 集群 4.2.拆分 4.2.1 应用拆分 4.2.2 数据库 4.3. 静态化 4.4.削峰 4.5.限流 5.总结 参考 保护高并发系统的三大利器&#xff1a;限流、熔…

【Proteus仿真】基于VSM 51单片机定时计数器闹钟例程

【Proteus仿真】基于VSM 51单片机定时计数器闹钟例程 🎬例程仿真功能操作演示: ✨本例程可从软件内部所提供的历程中找到,但是需要自行安装SDCC编译器才能对其源代码重新编译。 ⚡需要自行安装SDCC编译器。 🛠Proteus内部安装SDCC编译器方法 🌿将窗口切换到Source Co…