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列,列名为“时间”;后面就是读一个文件,解析一下时间…...
接口测试中缓存处理策略
在接口测试中,缓存处理策略是一个关键环节,直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性,避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明: 一、缓存处理的核…...
React hook之useRef
React useRef 详解 useRef 是 React 提供的一个 Hook,用于在函数组件中创建可变的引用对象。它在 React 开发中有多种重要用途,下面我将全面详细地介绍它的特性和用法。 基本概念 1. 创建 ref const refContainer useRef(initialValue);initialValu…...
DAY 47
三、通道注意力 3.1 通道注意力的定义 # 新增:通道注意力模块(SE模块) class ChannelAttention(nn.Module):"""通道注意力模块(Squeeze-and-Excitation)"""def __init__(self, in_channels, reduction_rat…...
条件运算符
C中的三目运算符(也称条件运算符,英文:ternary operator)是一种简洁的条件选择语句,语法如下: 条件表达式 ? 表达式1 : 表达式2• 如果“条件表达式”为true,则整个表达式的结果为“表达式1”…...
如何在看板中有效管理突发紧急任务
在看板中有效管理突发紧急任务需要:设立专门的紧急任务通道、重新调整任务优先级、保持适度的WIP(Work-in-Progress)弹性、优化任务处理流程、提高团队应对突发情况的敏捷性。其中,设立专门的紧急任务通道尤为重要,这能…...
Nuxt.js 中的路由配置详解
Nuxt.js 通过其内置的路由系统简化了应用的路由配置,使得开发者可以轻松地管理页面导航和 URL 结构。路由配置主要涉及页面组件的组织、动态路由的设置以及路由元信息的配置。 自动路由生成 Nuxt.js 会根据 pages 目录下的文件结构自动生成路由配置。每个文件都会对…...
Android Bitmap治理全解析:从加载优化到泄漏防控的全生命周期管理
引言 Bitmap(位图)是Android应用内存占用的“头号杀手”。一张1080P(1920x1080)的图片以ARGB_8888格式加载时,内存占用高达8MB(192010804字节)。据统计,超过60%的应用OOM崩溃与Bitm…...
AirSim/Cosys-AirSim 游戏开发(四)外部固定位置监控相机
这个博客介绍了如何通过 settings.json 文件添加一个无人机外的 固定位置监控相机,因为在使用过程中发现 Airsim 对外部监控相机的描述模糊,而 Cosys-Airsim 在官方文档中没有提供外部监控相机设置,最后在源码示例中找到了,所以感…...
现有的 Redis 分布式锁库(如 Redisson)提供了哪些便利?
现有的 Redis 分布式锁库(如 Redisson)相比于开发者自己基于 Redis 命令(如 SETNX, EXPIRE, DEL)手动实现分布式锁,提供了巨大的便利性和健壮性。主要体现在以下几个方面: 原子性保证 (Atomicity)ÿ…...
【Android】Android 开发 ADB 常用指令
查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...
