OpenSSL-3.0.3编程—封装EVP摘要计算为C++类EvpDigest
文章目录
- 使用OpenSSL推荐的EVP高级接口计算摘要
- EvpDigest 类定义
- 1.EvpDigest 头文件接口
- 2.EvpDigest 类函数实现
- 3.使用 EvpDigest 类计算摘要,文件 EvpDigestTest.cpp
- 4.摘要实现类简要说明
- 总结
使用OpenSSL推荐的EVP高级接口计算摘要
直接使用openssl evp接口对底层低级接口进行了抽象,比较便于封装成C++类,与之前的 Digest 类相比,不需要在各个方法调用之前使用 switch 进行摘要算法的判断
- 创建摘要上下文,分配空间
- 初始化指定摘要算法的上下文
- 更新数据。可以添加多次,比如"hello, world" 可以分两次更新,可以参考如下代码
- 计算摘要值。对第3步更新的所有的数据计算摘要,通过传出参数返回摘要值
- 使用 EVP_MD_CTX_free 释放资源(重要)
- 将第4步计算的二进制摘要值转换为十六进制或Base64输出,本步骤可省略,看具体需要采用合适的方式
EvpDigest 类定义
1.EvpDigest 头文件接口
#ifndef OPENSSL_01_EVPDIGEST_H
#define OPENSSL_01_EVPDIGEST_H#include <openssl/evp.h>
#include "DigestAlgo.h"
#include "CommonFun.h"# define SM3_DIGEST_LENGTH 32class EvpDigest {public:/*** 创建摘要对象,指定摘要算法* @param algo 摘要算法*/explicit EvpDigest(DigestAlgo algo);virtual ~EvpDigest();/*** 更新数据* @param str* @return*/int digestUpdate(const std::string& str);/*** 计算摘要结果* @return*/int digestFinal();/*** 按照十六进制输出摘要值*/void showDigestHex();private:/*** 摘要算法*/DigestAlgo digestAlgo;/*** 摘要上下文*/EVP_MD_CTX* context;/*** 指定存储摘要算法*/const EVP_MD* evpMd;/*** 摘要值*/unsigned char* digest;/*** 摘要字节长度*/unsigned int digestLength;
};#endif //OPENSSL_01_EVPDIGEST_H
2.EvpDigest 类函数实现
#include <openssl/md5.h>
#include <openssl/sha.h>
#include <iostream>
#include "EvpDigest.h"EvpDigest::EvpDigest(DigestAlgo algo) : digestAlgo(algo) {switch (digestAlgo) {case DigestAlgo::MD5:digestLength = MD5_DIGEST_LENGTH;evpMd = EVP_md5();break;case DigestAlgo::SHA1:digestLength = SHA_DIGEST_LENGTH;evpMd = EVP_sha1();break;case DigestAlgo::SHA224:digestLength = SHA224_DIGEST_LENGTH;evpMd = EVP_sha224();break;case DigestAlgo::SHA256:digestLength = SHA256_DIGEST_LENGTH;evpMd = EVP_sha256();break;case DigestAlgo::SHA384:digestLength = SHA384_DIGEST_LENGTH;evpMd = EVP_sha384();break;case DigestAlgo::SHA512:digestLength = SHA512_DIGEST_LENGTH;evpMd = EVP_sha512();break;case DigestAlgo::SM3:digestLength = SM3_DIGEST_LENGTH;evpMd = EVP_sm3();break;default:std::cout << "摘要算法类型错误..." << std::endl;exit(EXIT_FAILURE);}digest = new unsigned char[digestLength];// 1.创建摘要上下文,分配空间context = EVP_MD_CTX_new();if (context == nullptr) {handleErrors();}// 2.用指定摘要算法初始化上下文指针int ret = EVP_DigestInit_ex(context, evpMd, nullptr);if (ret != 1) {handleErrors();}
}EvpDigest::~EvpDigest() {// 6.释放资源delete[] digest;EVP_MD_CTX_free(context);std::cout << "析构函数调用..." << std::endl;
}int EvpDigest::digestUpdate(const std::string& str) {// 3.传入待计算摘要的原始数据,update。可以调用多次 updateint ret = EVP_DigestUpdate(context, str.c_str(), str.size());if (ret != 1) {handleErrors();}return ret;
}int EvpDigest::digestFinal() {// 4.计算哈希值int ret = EVP_DigestFinal_ex(context, digest, &digestLength);if (ret != 1) {handleErrors();}return 0;
}void EvpDigest::showDigestHex() {// 5.将二进制哈希值转换为十六进制输出char* digestHex = new char[digestLength * 2 + 1];for (int i = 0; i < digestLength; ++i) {sprintf(&digestHex[i * 2], "%02x", digest[i]);}std::cout << "摘要值: " << digestHex << std::endl;delete[] digestHex;
}
3.使用 EvpDigest 类计算摘要,文件 EvpDigestTest.cpp
#include "EvpDigest.h"int main(int argc, char* argv[]) {EvpDigest digest(DigestAlgo::SHA256);digest.digestUpdate("123456");digest.digestUpdate("123456");digest.digestFinal();digest.showDigestHex();return 0;
}
4.摘要实现类简要说明
函数 EVP_DigestInit_ex 的第二个参数可以指定摘要算法,如 EVP_sha1、EVP_sha224、EVP_sha256、EVP_sha3_256、EVP_sm3……另外,EVP_sha256 与 EVP_sha3_256 有啥区别还没明白,以后明白了再补充
特别说明: OpenSSL3 里面包含国密算法,如 sm2、sm3、sm4,若要使用sm3计算摘要,可以在函数 EVP_DigestInit_ex 第二个参数传入 EVP_sm3()
几个函数的使用步骤
- 步骤1: 在构造函数中使用 EVP_XXX 函数给算法类型成员 evpMd 赋值,提供给 EVP_DigestInit_ex 函数的第二个参数,EVP_MD_CTX_new 给摘要上下文指针分配内存,同时根据算法类型记录摘要值字节长度
- 步骤2: 在构造函数中使用 EVP_DigestInit_ex 函数指定摘要算法,并初始化上下文指针
- 步骤3: 在 digestUpdate 函数中使用 EVP_DigestUpdate 函数更新数据,可以调用多次
- 步骤4: 在 digestFinal 函数中使用 EVP_DigestFinal_ex 计算摘要
- 步骤5: 补充一个比较重要的步骤,在析构函数中使用 EVP_MD_CTX_free 释放 EVP_MD_CTX_new 分配的资源,delete 运算符释放其他资源
- 步骤6: showDigestHex 函数将二进制摘要值转换为十六进制输出
CommonFun.h 头文件中包含 handleErrors 函数的实现,请参考 前面的文章
总结
OpenSSL-3.0.3编程—封装EVP摘要计算为C++类EvpDigest相关推荐
- OpenSSL-3.0.3编程—采用EVP方式计算数据摘要
文章目录 使用OpenSSL推荐的EVP高级接口计算摘要 样例代码 推荐阅读 OpenSSL 官方 wiki 摘要实现类简要说明 handleErrors 函数 总结 使用OpenSSL推荐的EVP高 ...
- 基于openEuler的OpenSSL编译安装和编程基础
文章目录 基于openEuler的OpenSSL编译安装和编程基础 OpenSSL编译安装 OpenSSL命令的使用 OpenSSL编程 简单测试 BASE64算法 作业 参考资料 基于openEul ...
- VC2008下使用OpenSSL 1.0.0g(免编译)
摘要: 运行时库附加依赖项多线程(/MT)libeay32MT.lib ssleay32MT.lib多线程调试(/MTd)libeay32MTd.lib ssleay32... id="cp ...
- CloudSim3.0.3power编程examples及辅助类解析
CloudSim3.0.3power编程examples及辅助类解析 注:本文为旧文的markdown重制版 power编程依赖的底层主要类(PowerDataCenter.PowerDCBroker ...
- python面向对象编程 -- 封装、继承
面向对象编程 -- 封装.继承 面向对象编程三要素:封装.继承和多态.本文主要看和封装.继承相关的概念:在python中多态的概念比较模糊,本文不做讨论. 1 封装 封装:将数据和操作组装到一起,对外 ...
- 细说Android 4.0 NDK编程pdf
下载地址:网盘下载 <细说Android 4.0 NDK编程>内容简介:通过NDK,应用程序可以非常方便地实现Java与C∕C++代码的相互沟通.<细说Android 4.0 NDK ...
- openssl / vs2019 编译 openssl 1.0.2u 过程说明
一.准备 1.安装 perl http://strawberryperl.com/download/5.28.1.1/strawberry-perl-5.28.1.1-64bit.msi 2.下载 o ...
- vue 生成发布包_年轻人如何从0到1封装发布一个vue组件__Vue.js
封装发布组件是前端开发中非常重要的能力,通过对常用组件的封装可以提升团队开发的效率,避免重复劳作且不方便维护.好的组件的抽象和封装能让组件得到更广泛和多环境兼容的应用. 本文讲述了如何一步步从0到1封 ...
- matlab usb cam,Matlab环境下使用USB2.0摄像头编程image acquisition tools(读书笔记) | 学步园...
(1)Matlab环境下使用USB2.0摄像头编程 Matlab中的图像获取工具箱给我们提供了必要的函数,我们直接调用就可以了,主要就是简单的介绍如何使用该工具箱进行对USB2.0摄像头的编程. TA ...
最新文章
- 利用BH1750光度传感器测量一些发光体
- Algorithm:C++语言实现之贪心法算法相关问题
- while((ch=getchar())!=EOFch != '\n');消除非法输入
- 使用gparted live分区工具对VMware及ESXI(vsphere)虚拟机进行根目录扩容(可视化界面操作)
- flex页面布局练习--知乎
- openshift_在OpenShift上扩展Java EE微服务
- 基于java家教管理系统_基于jsp的家教信息管理-JavaEE实现家教信息管理 - java项目源码...
- java开发环境搭建--写给java新手
- 虚幻4 Object和序列化
- Linux操作Oracle(8)——Oracle数据库迁移全纪录(1) — 表空间 用户 权限迁移
- 遗传算法c语言 x^2,c语言遗传算法 解决 y=x2问题
- Excel中绘制斜线表头
- OpenCV显示中文字体
- php 完全前后端分离使用jwt,前后端分离,在 angular 8 中利用 JWT 进行身份认证
- Spark—15分钟教程
- AAAI最佳论文Informer 解读
- Android_版本控制_Git命令行介绍和使用说明
- 单片机开发-软件架构与系统设计(工程实现使用的也是轮询系统、前后台系统和多任务系统)
- 关于umdf 和 kmdf
- 《炬丰科技-半导体工艺》 双异质结双极晶体管的加速振荡