openssl+SM2开发实例一(含源码)
一、SM2算法介绍
SM2(国密算法2) 是中国国家密码管理局(CNCA)颁布的椭圆曲线密码算法标准,属于非对称加密算法。它基于椭圆曲线离散对数问题,提供了安全可靠的数字签名、密钥交换和公钥加密等功能。SM2被设计为适用于各种场景下的密码学应用,包括数字证书、数据加密、数字签名、身份认证等。
以下是SM2算法的一些关键特点和概要介绍:
-
非对称加密算法: SM2是一种非对称加密算法,意味着它使用两个密钥:公钥和私钥。公钥用于加密数据和验证签名,而私钥用于解密数据和生成签名。
-
椭圆曲线密码学: SM2基于椭圆曲线密码学(Elliptic Curve Cryptography,ECC),使用椭圆曲线上的点运算来实现加密和签名操作。
-
安全性: SM2采用了高强度的椭圆曲线参数,保障了算法的安全性。在适当的参数选择下,SM2被认为是安全可靠的。
-
性能优越: 与传统的RSA算法相比,SM2在相同安全性水平下使用更短的密钥长度,提供了更高的性能。
-
国家标准: SM2是中国国家密码算法标准,适用于中国国内的各种密码学应用,包括政府、金融、电信等领域。
-
数字签名和密钥交换: SM2可以用于生成数字签名,验证签名的有效性,以及进行安全的密钥交换,用于建立安全的通信通道。
由于SM2是中国的国家密码标准,它在中国国内得到了广泛的应用。SM2不仅提供了高度的安全性,还具备较好的性能,适用于多种密码学场景。
二、SM2代码实例
2.1 SM2加密 / SM2解密
以下是一个简单的C++代码示例,演示了如何使用OpenSSL库进行SM2加密和解密。在这个示例中,我们将SM2加密和解密的功能拆分为两个函数:sm2_encrypt() 和 sm2_decrypt()。
请注意,使用此示例代码前,请确保你的系统已经安装了OpenSSL库,并且链接时正确引入了OpenSSL的库文件。该示例仅供学习和参考,实际应用中,你需要根据你的需求和安全性要求进行更严格的错误处理和参数验证。
#include <openssl/evp.h>
#include <openssl/sm2.h>
#include <iostream>
#include <string>std::string sm2_encrypt(const std::string &plaintext, EVP_PKEY *pubkey) {EVP_PKEY_CTX *ctx;unsigned char *ciphertext = nullptr;size_t ciphertext_len;// 创建EVP_PKEY_CTXctx = EVP_PKEY_CTX_new(pubkey, nullptr);if (!ctx) {std::cerr << "Error creating EVP_PKEY_CTX for encryption" << std::endl;return "";}// 初始化加密操作if (EVP_PKEY_encrypt_init(ctx) <= 0) {std::cerr << "Error initializing encryption operation" << std::endl;EVP_PKEY_CTX_free(ctx);return "";}// 设置加密参数(这里可以设置一些参数,例如填充方式)// EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING);// 计算加密后的长度if (EVP_PKEY_encrypt(ctx, nullptr, &ciphertext_len, reinterpret_cast<const unsigned char*>(plaintext.c_str()), plaintext.length()) <= 0) {std::cerr << "Error computing ciphertext length" << std::endl;EVP_PKEY_CTX_free(ctx);return "";}// 分配内存并执行加密操作ciphertext = new unsigned char[ciphertext_len];if (EVP_PKEY_encrypt(ctx, ciphertext, &ciphertext_len, reinterpret_cast<const unsigned char*>(plaintext.c_str()), plaintext.length()) <= 0) {std::cerr << "Error encrypting data" << std::endl;delete[] ciphertext;EVP_PKEY_CTX_free(ctx);return "";}// 释放资源EVP_PKEY_CTX_free(ctx);// 返回加密后的数据(Base64编码)std::string encoded_ciphertext(reinterpret_cast<char*>(ciphertext), ciphertext_len);delete[] ciphertext;return encoded_ciphertext;
}std::string sm2_decrypt(const std::string &ciphertext, EVP_PKEY *privkey) {EVP_PKEY_CTX *ctx;unsigned char *plaintext = nullptr;size_t plaintext_len;// 创建EVP_PKEY_CTXctx = EVP_PKEY_CTX_new(privkey, nullptr);if (!ctx) {std::cerr << "Error creating EVP_PKEY_CTX for decryption" << std::endl;return "";}// 初始化解密操作if (EVP_PKEY_decrypt_init(ctx) <= 0) {std::cerr << "Error initializing decryption operation" << std::endl;EVP_PKEY_CTX_free(ctx);return "";}// 计算解密后的长度if (EVP_PKEY_decrypt(ctx, nullptr, &plaintext_len, reinterpret_cast<const unsigned char*>(ciphertext.c_str()), ciphertext.length()) <= 0) {std::cerr << "Error computing plaintext length" << std::endl;EVP_PKEY_CTX_free(ctx);return "";}// 分配内存并执行解密操作plaintext = new unsigned char[plaintext_len];if (EVP_PKEY_decrypt(ctx, plaintext, &plaintext_len, reinterpret_cast<const unsigned char*>(ciphertext.c_str()), ciphertext.length()) <= 0) {std::cerr << "Error decrypting data" << std::endl;delete[] plaintext;EVP_PKEY_CTX_free(ctx);return "";}// 释放资源EVP_PKEY_CTX_free(ctx);// 返回解密后的数据std::string decrypted_plaintext(reinterpret_cast<char*>(plaintext), plaintext_len);delete[] plaintext;return decrypted_plaintext;
}int main() {EVP_PKEY *pubkey = nullptr;EVP_PKEY *privkey = nullptr;// 生成SM2密钥对if (!EVP_PKEY_keygen_SM2(&pubkey, &privkey)) {std::cerr << "Error generating SM2 key pair" << std::endl;return 1;}std::string plaintext = "Hello, SM2!";std::string ciphertext = sm2_encrypt(plaintext, pubkey);std::string decrypted_text = sm2_decrypt(ciphertext, privkey);std::cout << "Original Text: " << plaintext << std::endl;std::cout << "Encrypted Text: " << ciphertext <<std::endl;std::cout << "Decrypted Text: " << decrypted_text << std::endl;EVP_PKEY_free(pubkey);EVP_PKEY_free(privkey);return 0;
}
请确保在实际使用时对错误进行适当处理,并根据实际需求进行参数配置。此示例中,使用了OpenSSL提供的SM2密钥生成函数,加密和解密操作的结果以字符串形式输出。在实际应用中,你可能需要对加密后的数据进行Base64编码以方便传输。
2.2 SM2签名
2.2.1 SM2签名步骤
SM2签名的过程通常包括以下步骤:
-
生成密钥对: 签名方首先需要生成自己的SM2公钥和私钥。公钥用于验证签名,私钥用于生成签名。
-
计算消息的哈希值: 对待签名的消息进行哈希操作,通常使用SM3算法生成消息的摘要(哈希值)。
-
生成随机数: 生成一个随机数(称为
k),该随机数需要满足一定的条件,以保障签名的安全性。在SM2中,k的生成需要满足一定的随机性和不可预测性。 -
计算椭圆曲线点: 使用随机数
k计算椭圆曲线上的点(k * G,其中G是椭圆曲线的基点),得到一个椭圆曲线点(x1, y1)。 -
计算
r值: 将椭圆曲线点的横坐标x1对一个固定数取模,得到一个整数r。如果r等于0,则需要重新选择随机数k并重新计算。 -
计算
s值: 计算签名的另一个部分s,公式为: s = ( ( h a s h + r ⋅ d ) / k ) m o d n s = ((hash + r \cdot d) / k) \mod n s=((hash+r⋅d)/k)modn 其中,hash是消息的哈希值,d是私钥,n是椭圆曲线的阶数。 -
验证
r和s: 将r和s作为签名的两个组成部分,并与消息一起发送给验证方。验证方使用签名者的公钥、消息的哈希值、r和s进行验证。验证的详细步骤包括使用公钥计算椭圆曲线点,验证r的范围和计算(s \cdot G + r \cdot PK)等。如果验证通过,则签名有效。
在SM2签名过程中,随机数k的选择和签名的正确性非常关键,不当的随机数选择可能导致签名的不安全性。因此,在实际应用中,随机数的生成需要特别注意,通常使用专门的随机数生成库或硬件随机数生成模块来确保随机性和不可预测性。
2.2.2 SM2签名C++开发实例
2.3 SM2密钥交换
2.3.1 SM2密钥交换步骤
是的,SM2算法可以用于密钥交换。在SM2中,密钥交换是通过Diffie-Hellman密钥交换协议的椭圆曲线密码学版本来实现的。SM2密钥交换的过程基于椭圆曲线离散对数问题,该问题在椭圆曲线密码学中是困难的,因此使得SM2密钥交换具备了很高的安全性。
SM2密钥交换的流程通常包括以下步骤:
-
生成临时密钥对: 通信双方分别生成自己的临时私钥和对应的临时公钥。这两个临时密钥对仅在当前密钥交换会话中使用。
-
计算共享秘密: 通信双方分别使用自己的临时私钥和对方的临时公钥,通过椭圆曲线上的点运算计算出一个共享的秘密值。
-
生成共享密钥: 使用共享的秘密值作为密钥生成算法的输入,生成对称密钥,该密钥可以用于后续的加密和解密通信内容。
-
销毁临时密钥: 在生成共享密钥之后,临时私钥和临时公钥可以被销毁,因为它们不再需要。
SM2密钥交换的安全性建立在椭圆曲线离散对数问题的困难性上,确保了在不共享密钥的情况下,通信双方可以协商出一个共享密钥,从而实现了安全的密钥交换。
三、openssl SM2 命令操作
3.1 openssl SM2 加密
3.2 openssl sm2 解密
3.3 openssl SM2 签名
3.3 openssl SM2 验签(签名校验)
相关文章:
openssl+SM2开发实例一(含源码)
一、SM2算法介绍 SM2(国密算法2) 是中国国家密码管理局(CNCA)颁布的椭圆曲线密码算法标准,属于非对称加密算法。它基于椭圆曲线离散对数问题,提供了安全可靠的数字签名、密钥交换和公钥加密等功能。SM2被设…...
操作系统 | 编写内核
🌈个人主页:Sarapines Programmer🔥 系列专栏:《操作系统实验室》🔖少年有梦不应止于心动,更要付诸行动。 目录结构 1. 操作系统实验之编写内核 1.1 实验目的 1.2 实验内容 1.3 实验步骤 1.4 实验过程 …...
Rust逆向学习 (4)
Reverse for Struct Rust中的结构体是一个重要的内容,由于Rust中没有类的概念,因此其他编程语言中的封装、继承、多态与Rust中的表现都有较大差异。 我们使用参考书中的一个示例开始进行分析。 Struct 初始化 struct User {username: String,email: …...
uniapp vue2 vuex 持久化
1.vuex的使用 一、uniapp中有自带vuex插件,直接引用即可 二、在项目中新建文件夹store,在main.js中导入 在根目录下新建文件夹store,在此目录下新建index.js文件 index.js import Vue from vueimport Vuex from vuexVue.use(Vuex)const store new Vuex.Store(…...
【媒体邀约】媒体宣传——企业成长的催化剂
传媒如春雨,润物细无声,大家好,我是51媒体网胡老师。 媒体宣传是企业成长的催化剂,它在各种方面对企业的成功和发展起到了关键作用。 1. 曝光和知名度: 媒体宣传可以将企业和其产品或服务推向广泛的受众,…...
ansible问题排查
拷贝模板时报错:AnsibleError: template error while templating string: Missing end of comment tag. 原因 shell脚本中地{#和jinja中的语法comment tag相同,而且只有一半,导致无法渲染导致。 解决 在有语法冲突的地方使用组合标签{% r…...
7天入门python系列之第四天python数据结构
第3天主要是学习Python的函数和模块 编者打算开一个python 初学主题的系列文章,用于指导想要学习python的同学。关于文章有任何疑问都可以私信作者。对于初学者想在7天内入门Python,这是一个紧凑的学习计划。但并不是不可完成的。第四天开始python 数据…...
远程电脑未连接显示器时分辨率太小的问题处理
背景:单位电脑显示器坏了,使用笔记本通过向日葵远程连接,发现分辨率只有800*600并且不能修改,网上找了好久找到了处理方法这里记录一下,主要用到的是一个虚拟显示器软件usbmmidd_v2 1)下载usbmmidd_v2 2)…...
Java 设计模式——解释器模式
目录 1.概述2.结构3.案例实现3.1.抽象表达式类3.2.终结表达式3.3.非终结表达式3.4.环境类3.5.测试 4.优缺点5.使用场景 1.概述 (1)如下图,设计一个软件用来进行加减计算。我们第一想法可能就是使用工具类,提供对应的加法和减法的…...
面试经典150题——Day37
文章目录 一、题目二、题解 一、题目 73. Set Matrix Zeroes Given an m x n integer matrix matrix, if an element is 0, set its entire row and column to 0’s. You must do it in place. Example 1: Input: matrix [[1,1,1],[1,0,1],[1,1,1]] Output: [[1,0,1],[0,…...
在 Arduino IDE 2.0 中安装 ESP32 板(Windows、Mac OS X、Linux)
有一个新的 Arduino IDE——Arduino IDE 2.0(测试版)。在本教程中,您将学习如何在 Arduino IDE 2.0 中安装 ESP32 板并将代码上传到板。本教程与 Windows、Mac OS X 和 Linux 操作系统兼容。 据 Arduino 网站称:“ Arduino IDE 2.…...
西门子S7-1200PLC混合通信编程(ModbusTcp和UDP通信)
S7-1200PLC的MODBUS-TCP通信 西门子PLC ModbusTcp通信访问网关后从站(SCL语言轮询状态机)-CSDN博客文章浏览阅读305次。西门子PLC的ModbusTcp通信在专栏已有很多文章介绍,所不同的是每个项目的通信需求都略有不同,今天我们以访问网关后的三个从站数据来举例,给出轮询的推荐…...
Hbase 迁移小结:从实践中总结出的最佳迁移策略
在数据存储和处理领域,HBase作为一种分布式、可扩展的NoSQL数据库,被广泛应用于大规模数据的存储和分析。然而,随着业务需求的变化和技术发展的进步,有时候我们需要将现有的HBase数据迁移到其他环境或存储系统。HBase数据迁移是一…...
键盘win键无法使用,win+r不生效、win键没反应、Windows键失灵解决方案(亲测可以解决)
最近几天发现自己笔记本的win键无法使用,win失灵了,但是外接键盘后则正常:。 这个问题困扰了我一周,我都以为自己的枪神坏了。 寻找了几个解决方法,网上看了好多好多稀里糊涂的办法,都是不管用的,这里给大…...
1. 深度学习——激活函数
机器学习面试题汇总与解析——激活函数 本章讲解知识点 什么是激活函数? 为什么要使用激活函数? 详细讲解激活函数 本专栏适合于Python已经入门的学生或人士,有一定的编程基础。本专栏适合于算法工程师、机器学习、图像处理求职的学生或人…...
chatglm3-6b部署及微调
chatglm3-6b部署及微调 modelscope: https://modelscope.cn/models/ZhipuAI/chatglm3-6b/filesgithub: https://github.com/THUDM/ChatGLM3镜像: ubuntu20.04-cuda11.7.1-py38-torch2.0.1-tf1.15.5-1.8.1v100 16G现存 单卡 安装 软件依赖 # 非必要无需执行 # pip install -…...
Hive 知识点八股文记录 ——(二)优化
函数 UDF:用户定义函数 UDAF:用户定义聚集函数 UDTF:用户定义表生成函数 建表优化 分区建桶 创建表时指定分区字段 PARTITIONED BY (date string)指定分桶字段和数量 CLUSTERED BY (id) INTO 10 BUCKETS插入数据按分区、分桶字段插入 …...
计算机技术专业CSIT883系统分析与项目管理介绍
文章目录 前言一、学科学习成果二、使用步骤三、最低出勤要求四、讲座时间表五、项目管理 前言 本课程介绍了信息系统开发中的技术和技术,以及与管理信息技术项目的任务相关的方法和过程。 它研究了系统分析师、客户和用户在系统开发生命周期中的互补角色。 它涵盖…...
gitlab安装地址
镜像地址: Index of /gitlab-ce/yum/el7/ | 清华大学开源软件镜像站 | Tsinghua Open Source Mirror wget Index of /gitlab-ce/yum/el7/ | 清华大学开源软件镜像站 | Tsinghua Open Source Mirror rpm -i gitlab-ce-15.9.1-ce.0.el7.x86_64.rpm 一直提示 &#x…...
Spark处理方法_提取文件名中的时间
需求描述 通过读取目录下的类似文件的datapath路径的文件名及文件内容,需要将读取的每一个文件的文件名日期解析出来,并作为读取当前文件内容递归读取当前文件一个df列,列名为“时间”;后面就是读一个文件,解析一下时间…...
【根据当天日期输出明天的日期(需对闰年做判定)。】2022-5-15
缘由根据当天日期输出明天的日期(需对闰年做判定)。日期类型结构体如下: struct data{ int year; int month; int day;};-编程语言-CSDN问答 struct mdata{ int year; int month; int day; }mdata; int 天数(int year, int month) {switch (month){case 1: case 3:…...
Linux 文件类型,目录与路径,文件与目录管理
文件类型 后面的字符表示文件类型标志 普通文件:-(纯文本文件,二进制文件,数据格式文件) 如文本文件、图片、程序文件等。 目录文件:d(directory) 用来存放其他文件或子目录。 设备…...
DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径
目录 一、智慧能源微电网优化调度概述1.1 智慧能源微电网概念1.2 优化调度的重要性1.3 目前面临的挑战 二、DeepSeek 技术探秘2.1 DeepSeek 技术原理2.2 DeepSeek 独特优势2.3 DeepSeek 在 AI 领域地位 三、DeepSeek 在微电网优化调度中的应用剖析3.1 数据处理与分析3.2 预测与…...
【CSS position 属性】static、relative、fixed、absolute 、sticky详细介绍,多层嵌套定位示例
文章目录 ★ position 的五种类型及基本用法 ★ 一、position 属性概述 二、position 的五种类型详解(初学者版) 1. static(默认值) 2. relative(相对定位) 3. absolute(绝对定位) 4. fixed(固定定位) 5. sticky(粘性定位) 三、定位元素的层级关系(z-i…...
什么是Ansible Jinja2
理解 Ansible Jinja2 模板 Ansible 是一款功能强大的开源自动化工具,可让您无缝地管理和配置系统。Ansible 的一大亮点是它使用 Jinja2 模板,允许您根据变量数据动态生成文件、配置设置和脚本。本文将向您介绍 Ansible 中的 Jinja2 模板,并通…...
智能AI电话机器人系统的识别能力现状与发展水平
一、引言 随着人工智能技术的飞速发展,AI电话机器人系统已经从简单的自动应答工具演变为具备复杂交互能力的智能助手。这类系统结合了语音识别、自然语言处理、情感计算和机器学习等多项前沿技术,在客户服务、营销推广、信息查询等领域发挥着越来越重要…...
Go 语言并发编程基础:无缓冲与有缓冲通道
在上一章节中,我们了解了 Channel 的基本用法。本章将重点分析 Go 中通道的两种类型 —— 无缓冲通道与有缓冲通道,它们在并发编程中各具特点和应用场景。 一、通道的基本分类 类型定义形式特点无缓冲通道make(chan T)发送和接收都必须准备好࿰…...
适应性Java用于现代 API:REST、GraphQL 和事件驱动
在快速发展的软件开发领域,REST、GraphQL 和事件驱动架构等新的 API 标准对于构建可扩展、高效的系统至关重要。Java 在现代 API 方面以其在企业应用中的稳定性而闻名,不断适应这些现代范式的需求。随着不断发展的生态系统,Java 在现代 API 方…...
Modbus RTU与Modbus TCP详解指南
目录 1. Modbus协议基础 1.1 什么是Modbus? 1.2 Modbus协议历史 1.3 Modbus协议族 1.4 Modbus通信模型 🎭 主从架构 🔄 请求响应模式 2. Modbus RTU详解 2.1 RTU是什么? 2.2 RTU物理层 🔌 连接方式 ⚡ 通信参数 2.3 RTU数据帧格式 📦 帧结构详解 🔍…...
微服务通信安全:深入解析mTLS的原理与实践
🔥「炎码工坊」技术弹药已装填! 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 一、引言:微服务时代的通信安全挑战 随着云原生和微服务架构的普及,服务间的通信安全成为系统设计的核心议题。传统的单体架构中&…...
