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列,列名为“时间”;后面就是读一个文件,解析一下时间…...
MPNet:旋转机械轻量化故障诊断模型详解python代码复现
目录 一、问题背景与挑战 二、MPNet核心架构 2.1 多分支特征融合模块(MBFM) 2.2 残差注意力金字塔模块(RAPM) 2.2.1 空间金字塔注意力(SPA) 2.2.2 金字塔残差块(PRBlock) 2.3 分类器设计 三、关键技术突破 3.1 多尺度特征融合 3.2 轻量化设计策略 3.3 抗噪声…...
日语AI面试高效通关秘籍:专业解读与青柚面试智能助攻
在如今就业市场竞争日益激烈的背景下,越来越多的求职者将目光投向了日本及中日双语岗位。但是,一场日语面试往往让许多人感到步履维艰。你是否也曾因为面试官抛出的“刁钻问题”而心生畏惧?面对生疏的日语交流环境,即便提前恶补了…...
五年级数学知识边界总结思考-下册
目录 一、背景二、过程1.观察物体小学五年级下册“观察物体”知识点详解:由来、作用与意义**一、知识点核心内容****二、知识点的由来:从生活实践到数学抽象****三、知识的作用:解决实际问题的工具****四、学习的意义:培养核心素养…...
【配置 YOLOX 用于按目录分类的图片数据集】
现在的图标点选越来越多,如何一步解决,采用 YOLOX 目标检测模式则可以轻松解决 要在 YOLOX 中使用按目录分类的图片数据集(每个目录代表一个类别,目录下是该类别的所有图片),你需要进行以下配置步骤&#x…...
关键领域软件测试的突围之路:如何破解安全与效率的平衡难题
在数字化浪潮席卷全球的今天,软件系统已成为国家关键领域的核心战斗力。不同于普通商业软件,这些承载着国家安全使命的软件系统面临着前所未有的质量挑战——如何在确保绝对安全的前提下,实现高效测试与快速迭代?这一命题正考验着…...
力扣热题100 k个一组反转链表题解
题目: 代码: func reverseKGroup(head *ListNode, k int) *ListNode {cur : headfor i : 0; i < k; i {if cur nil {return head}cur cur.Next}newHead : reverse(head, cur)head.Next reverseKGroup(cur, k)return newHead }func reverse(start, end *ListNode) *ListN…...
计算机基础知识解析:从应用到架构的全面拆解
目录 前言 1、 计算机的应用领域:无处不在的数字助手 2、 计算机的进化史:从算盘到量子计算 3、计算机的分类:不止 “台式机和笔记本” 4、计算机的组件:硬件与软件的协同 4.1 硬件:五大核心部件 4.2 软件&#…...
比较数据迁移后MySQL数据库和OceanBase数据仓库中的表
设计一个MySQL数据库和OceanBase数据仓库的表数据比较的详细程序流程,两张表是相同的结构,都有整型主键id字段,需要每次从数据库分批取得2000条数据,用于比较,比较操作的同时可以再取2000条数据,等上一次比较完成之后,开始比较,直到比较完所有的数据。比较操作需要比较…...
在树莓派上添加音频输入设备的几种方法
在树莓派上添加音频输入设备可以通过以下步骤完成,具体方法取决于设备类型(如USB麦克风、3.5mm接口麦克风或HDMI音频输入)。以下是详细指南: 1. 连接音频输入设备 USB麦克风/声卡:直接插入树莓派的USB接口。3.5mm麦克…...
Python网页自动化Selenium中文文档
1. 安装 1.1. 安装 Selenium Python bindings 提供了一个简单的API,让你使用Selenium WebDriver来编写功能/校验测试。 通过Selenium Python的API,你可以非常直观的使用Selenium WebDriver的所有功能。 Selenium Python bindings 使用非常简洁方便的A…...
