基于GD32F470的mbedtls 3DES算法测试

2023-10-27

3DES加密算法介绍

3DES数据加密算法是一种可逆的对称加密算法,也称三重数据加密算法。3DES块加密算法的设计用来提供一种相对简单的方法,即通过增加DES的密钥长度来避免类似的攻击,而不是设计一种全新的密码算法,目前3DES作为DES的过渡算法已经逐渐被更安全的AES代替。

DES的秘钥长度是8字节,而3DES的秘钥长度是24字节。3DES 是为了增加DES 的强度,将DES 重复计算3次所得到的一种密码算法。但3DES 并不是进行三次DES 加密(加密->加密->加密),而是加密->解密->加密的过程。这样做的目的是为了3DES 能够兼容普通的DES。
对于3DES算法秘钥来说,24个字节被分为三组,每组8个字节,分别用于三次DES计算的秘钥,所以当DES 中所有的密钥都是相同时,3DES 也就等同于普通的DES了。这就让3DES 具备了向下的兼容性。

加密模式

ECB模式(Electronic CodeBook mode):电子密码本模式

ECB (电子密码本)模式是最简单的块密码加密模式,加密前根据数据块大小分成若干块,之后将每块使用相同的密钥单独通过块加密器加密。这种加密模式的优点就是简单,不需要初始化向量(IV),每个数据块独立进行加/解密,利于并行计算,加/解密效率很高。但这种模式中,所有数据都采用相同密钥进行加/解密,也没有经过任何逻辑运算,相同明文得到相同的密文,所以可能导致“选择明文攻击”的发生。

CBC模式(Cipher Block Chaining mode):密码分组链模式

CBC (密码分组链接)模式是先将明文切分成若干小块,然后每个小块与初始块或者上一段的密文段进行逻辑异或运算后,再用密钥进行加密。第一个明文块与一个叫初始化向量的数据块进行逻辑异或运算。这样就有效的解决了ECB模式所暴露出来的问题,即使两个明文块相同,加密后得到的密文块也不相同。但是缺点也相当明显,如加密过程复杂,效率低等。

CFB模式(Cipher FeedBack mode):密码反馈模式

与ECB和CBC模式只能够加密块数据不同,CFB模式能够将密文转化成为流密文。这种加密模式中,由于加密流程和解密流程中被块加密器加密的数据是前块的密文,因此即使本块明文数据的长度不是数据块大小的整数倍也是不需要填充的,这保证了数据长度在加密前后是相同的。

OFB模式(Output FeedBack mode):输出反馈模式

不再直接加密明文块,其加密过程是先使用块加密器生成密钥流,然后再将密钥流和明文流进行逻辑异或运算得到密文流。

CTR模式(CounTeR mode):计时器模式

是一种通过将逐次累加的计算器进行加密来生成密钥流的流密码。每一个分组对应一个逐次累加的计数器,并通过计数器进行加密来生成密钥流。也就是说,最终的密文分组是通过将计数器加密得到的比特序列,与明文分组进行XOR而得到的。

图文详解可参考: 传送门

填充方式

由于块密码只能对确定长度的数据块进行处理,明文会被以64bit为一组划分为若干组进行加密,每一组使用DES算法由明文获得密文。可是待加密的明文并不能保证总是可以正好分成若干个64bit的组,最后一组正好满64bit的可能性往往是比较低的,那么为了加密方便,应该怎么办呢,Padding就是用来解决这个问题的。
3DES主要的填充方式有如下几种:

zeropadding

所有需要填充的地方都以0填充。

pkcs7padding

填充的内容是需要填充的字节数。如果最后一个数据块长度为len,每个块的长度为k,len恰好等于k时,则需要在后面再添加一个完整的padding块。例如是以每8byte为一块,最后一块有8byte,则需要填充8byte的0x08。

pkcs5padding

PKCS5 和 PKCS7 的唯一区别是PKCS5只能用来填充64bit(8bytes)的数据块,除此之外可以混用。

示例代码

mbedtls包含了3DES加解密模块,使用起来也十分方便,在高级语言中(java等),一般3DES加密后会以base64的形式输出,恰好mbedtls也集成了base64编解码模块,废话不多说,直接上代码:

#include <stdio.h>
#include "mbedtls/aes.h"
#include "mbedtls/des.h"
#include "mbedtls/ctr_drbg.h"
#include "mbedtls/entropy.h"

int main(int argc, char *argv[])
{
    unsigned char input[2048] = {"0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399"};
    unsigned char output[2048] = {0};
    unsigned char key[] = {"123456781234567812345678"};

    UINT64 start_time = 0;
    UINT64 des3_encrypt_time = 0;
    UINT64 base64_encode_time = 0;
    UINT64 base64_decode_time = 0;
    UINT64 des3_decrypt_time = 0;

    mbedtls_des3_context ctx;
    int data_len = strlen(input); // 数据长度
    printf("data_len = %d\r\n", data_len);
    int len = (data_len / 8 + (data_len % 8 ? 1: 0)) * 8;  // 长度补为8的整数倍
    printf("padding len = %d\r\n", len);
    printf("原始数据:\r\n%s\r\n", input);

	start_time = LOS_CurrNanosec(); // 开始计时

    mbedtls_des3_init(&ctx);
    mbedtls_des3_set3key_enc(&ctx, key);
    
// 使能 pkcs5padding 填充方式
#if 1
    if(data_len == len) {
        len += 8;
    }
    for(int i = data_len; i < len; i++) {
        input[i] = len - data_len;
    }
#endif

    for(int i=0; i<len; i+=8) {
        mbedtls_des3_crypt_ecb(&ctx, &input[i], &output[i]);
    }
    
	des3_encrypt_time = LOS_CurrNanosec();  // 原始数据加密完成

    size_t base64_len;
    unsigned char *encode_buf = NULL;
    mbedtls_base64_encode( NULL, 0, &base64_len, output, len);
    encode_buf = (unsigned char *)calloc(1, base64_len);
    mbedtls_base64_encode(encode_buf, base64_len, &base64_len, output, len);

    base64_encode_time = LOS_CurrNanosec();  // base64编码完成
    printf("加密后HEX: \r\n");
    for(int i=0; i<len; i++) {
        printf("%02x",output[i]);
    }
    printf("\r\n");
    printf("加密后base64:\r\n%s\r\n",encode_buf);
    printf("\r\n\r\n====================================\r\n");
	printf("3DES加密耗时:\t\t%lldns\r\n", des3_encrypt_time - start_time);
	printf("base64编码耗时:\t\t%lldns\r\n", base64_encode_time - des3_encrypt_time);
	printf("加密总耗时:\t\t%lldns\r\n", base64_encode_time - start_time);
    printf("====================================\r\n\r\n");

//  --------------------------- 开始解密
    start_time = LOS_CurrNanosec(); // 开始计时

    size_t result_len;
    memset(output, 0, sizeof(output));    // 清空output buffer,用于接收base64解码结果

    mbedtls_base64_decode( output, sizeof(output), &result_len, encode_buf, base64_len);

    base64_decode_time = LOS_CurrNanosec(); // 解码完成
    if(result_len%8 != 0) {
        printf("base64解码数据不符合3DES加密数据格式! result_len = %d\r\n", result_len);
        goto DES_Exit;
    }

    printf("base64解码后HEX: \r\n");
    for(int i=0; i<result_len; i++) {
        printf("%02x",output[i]);
    }
    printf("\r\n");

    mbedtls_des3_set3key_dec(&ctx, key);
    memset(input, 0, sizeof(input));    // 清空输入buffer,用于接收3DES解密结果
    for(int i=0; i<result_len; i+=8) {
        mbedtls_des3_crypt_ecb(&ctx, &output[i], &input[i]);
    }

    unsigned char padding_size = input[result_len-1];
    if(padding_size <= 0 || padding_size > 8){
        printf("解析失败, padding错误! padding_size = %d\r\n", padding_size);
        goto DES_Exit;
    }

    data_len = result_len - padding_size;
    input[data_len] = '\0';  // 添加结束符
    des3_decrypt_time = LOS_CurrNanosec(); // 3DES解密完成
    printf("解密后原始数据为:\r\n%s\r\n",input);
    printf("\r\n\r\n====================================\r\n");
	printf("base64解码耗时:\t\t%lldns\r\n", base64_decode_time - start_time);
    printf("3DES解密耗时:\t\t%lldns\r\n", des3_decrypt_time - base64_decode_time);
	printf("解密总耗时:\t\t%lldns\r\n", des3_decrypt_time - start_time);
    printf("====================================\r\n\r\n");

DES_Exit:
    mbedtls_des3_free(&ctx);
}

程序运行

如下为GD32F470单片机上的运行结果,可供参考:
在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

基于GD32F470的mbedtls 3DES算法测试 的相关文章

  • ESP32的开发环境SDK4.3.1版本和编译环境搭建

    首先 到乐鑫的官网下载一个最完整的安装包 地址为 https dl espressif com dl esp idf idf 4 3 在这分为两种 在线安装和离线安装 在线安装与离线安装的区别 在线安装程序非常小 可以安装 ESP IDF

随机推荐

  • Mysql建表出现错误:ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that correspo

    Mysql命令行sql语句建表报错 这里是你的SQL语法有错误 查看与MySQL服务器版本对应的手册 以确定使用 我的问题是sql语句里反引号用成了单引号 我这里用的是英文中的单引号 所以会有语法报错 正确的应该是键盘ESC键下的反引号 此
  • Python, Numpy求 list 数组均值,方差,标准差

    代码如下 import numpy as np array 1 3 5 7 9 求均值 arr mean np mean array 求方差 arr var np var array 求标准差 arr std np std array dd
  • 第二十八篇 SeNet模型解析

    文章目录 一 SENet概述 二 SENet 结构组成详解 三 详细的计算过程 SE模块代码详解 SENet 在具体网络中应用 代码实现SE ResNet 第一个残差模块 第二个残差模块 SEResNet18 SEResNet34模型的完整
  • 毕业设计 基于stm32的智能快递仓库环境监控系统 - 物联网 嵌入式

    本次设计的快递仓库的火灾报警系统通过主控单元将各个传感器的参数值采集回来 包括与消防安全相关的温度 湿度 烟雾等 主控制器 数据采集回来之后通过无线的方式将数据上传到远端的上位机上 由于这些参数都是有一个安全阈值的 当达到这个阈值的时候很可
  • ubuntu 17.10, cuda 9.1, cuDNN 7.0 安装caffe时runtest报错

    如果在runtest caffe时报如下错误 则 可将Makefile中 Debugging ifeq DEBUG 1 COMMON FLAGS DDEBUG g O0 NVCCFLAGS G else COMMON FLAGS DNDEB
  • 最全的cursor问题解答 The most complete Cursor question answer 2023.6.27

    2023 6 27 目前最新版本是Cursor Setup 0 2 35 x64 官网是https www cursor so 作者是https twitter com amanrsanger 使用操作 Ctrl k Edit Instru
  • 终于满足了我司QA的接口自动化测试统计报表要求

    以前我司接口测试用的工具比较多 有postman jmeter等 不同部门用的工具还不一样 即使同一部门开发自测用的接口测试工具和测试用的可能都不一样 项目到提测阶段 QA都会要求我们测试人员统计 项目有多少接口 是否每个接口都有被接口自动
  • 人生感悟之——因果关系

    2020年了 31岁 算是步入中年 偶有感悟 记录在案 待来年回头印证 近年来的感悟是 做事踏踏实实 实事求是很重要 有一是一 适当夸大我自己的能力是可以 但是夸的太大 未来的某一天我会付出代价 至少夸大的部分我需要花费足够的时间的努力来补
  • Protobuf如何集成到C++环境中(VS2019)

    文章目录 前言 下载安装Protocol Compiler和Protobuf Runtime 下载 编译安装Protobuf Runtime 使用Protocol Compiler生成 cc和 h文件 VS工程的配置 测试 前言 Proto
  • Spark集群搭建超详细教程

    Spark3 0 0集群搭建 前言 集群搭建具体步骤 Standalone模式 1 下载 spark 3 0 0 的jar包 2 上传并解压 3 配置SPARK HOME环境变量 4 修改配置 4 1 修改 spark defaults c
  • 课题:交通标志识别——设计思路与实现步骤记录

    一 准备数据集 选取两个典型的交通标志数据集 德国交通标志数据集GTSRB 与比利时交通标志数据集 选取两个数据集原因 1 便于后续对测试结果的对比 以及准确率差别的分析 2 二者图片格式相似 同样的程序二者兼容 无需重新编写代码 3 二者
  • 第10节 文件共享服务器—创建/访问共享文件及禁用共享服务

    这里写目录标题 0 引言 1 共享服务器概述 2 创建共享实验 2 1 创建共享文件夹并访问 2 2 创建隐藏共享文件夹并访问 3 权限控制逻辑 3 1 父子级文件共享权限的继承 3 2 远程权限与NTFS权限的控制关系 4 常用的与共享相
  • Vue+MySQL实现登录注册案例

    Vue MySQL实现登录注册案例 1 新建vue项目并连接数据库 具体步骤见vue连接mysql数据库 2 新建登录页面 注册页面和首页 在src views文件夹下 新建 login vue 登录页面 register vue 注册页面
  • 淘宝商品列表数据接口(支持价格、销量排序)

    淘宝商品列表数据接口是淘宝提供的一种可以获取淘宝商品信息的接口 通过该接口 可以获取到具有一定规则的商品信息 例如按照价格排序 按照销量排序等 接口返回的数据格式为JSON格式 可以方便地处理数据 我们可以通过调用淘宝提供的API 使用GE
  • Python计算机视觉编程 第一章 基本的图像操作和处理

    第一章 基本的图像操作和处理 1 1 PIL Python图像处理类库 1 1 1转换图像格式 1 1 2创建缩略图 1 1 3复制和粘贴图像区域 1 1 4调整尺寸和旋转 1 2Matplotlib 1 2 1绘制图像 点和线 1 2 2
  • 剑指 Offer 68 - II. 二叉树的最近公共祖先 -- 递归

    0 题目描述 leetcode原题链接 剑指 Offer 68 II 二叉树的最近公共祖先 1 递归解法 代码思路 递归查询两个节点p q 如果某个节点等于节点p或节点q 则返回该节点的值给父节点 如果当前节点的左右子树分别包括p和q节点
  • python--hashlib加密模块

    Python的hashlib提供了常见的摘要算法 如MD5 SHA1等等 什么是摘要算法呢 摘要算法又称哈希算法 散列算法 它通过一个函数 把任意长度的数据转换为一个长度固定的数据串 通常用16进制的字符串表示 摘要算法就是通过摘要函数f
  • ov9650摄像头驱动之——linux内核v4l2架构分析1

    本系列准备分为3 4篇来讲 因为说的太多会比较乱 v4l2视频驱动主要涉及几个知识点 摄像头方面的知识 摄像头厂家提供的芯片手册可以查看 要了解选用的摄像头的特性 包括访问控制方法 各种参数的配置方法 信号输出类型等 Camera解码器 控
  • Linux系统之wget命令的基本使用

    Linux系统之wget命令的基本使用 一 wget命令介绍 二 本次实践环境 三 wget命令的使用帮助 3 1 wget命令的基本语法 3 2 wget选项解释 四 安装wget工具 4 1 检查yum仓库状态 4 2 安装wget工具
  • 基于GD32F470的mbedtls 3DES算法测试

    3DES加密算法介绍 3DES数据加密算法是一种可逆的对称加密算法 也称三重数据加密算法 3DES块加密算法的设计用来提供一种相对简单的方法 即通过增加DES的密钥长度来避免类似的攻击 而不是设计一种全新的密码算法 目前3DES作为DES的