6.开源非对称加密算法SM2实现
6.开源非对称加密算法SM2实现
前期内容导读:
- 开源加解密RSA/AES/SHA1/PGP/SM2/SM3/SM4介绍
- 开源AES/SM4/3DES对称加密算法介绍及其实现
- 开源AES/SM4/3DES对称加密算法的验证实现
- 开源非对称加密算法RSA/SM2实现及其应用
- 开源非对称加密算法RSA实现
1. 开源组件 非对称秘钥加密介绍
- 加密组件引入方法:
<dependency><groupId>com.biuqu</groupId><artifactId>bq-encryptor</artifactId><version>1.0.1</version> </dependency>
1.1 SM2的加解密实现
- 加解密核心逻辑
public byte[] doCipher(byte[] data, byte[] key, int cipherMode) {SM2Engine.Mode mode = SM2Engine.Mode.C1C2C3;if (!this.getPaddingMode().equalsIgnoreCase(String.valueOf(DEFAULT_MODE))){mode = SM2Engine.Mode.C1C3C2;}SM2Engine sm2Engine = new SM2Engine(mode);this.initSm2Engine(sm2Engine, key, cipherMode);try{return sm2Engine.processBlock(data, 0, data.length);}catch (Exception e){throw new EncryptionException("failed to do sm2 cipher.", e);} }private void initSm2Engine(SM2Engine sm2Engine, byte[] key, int cipherMode) {if (Cipher.ENCRYPT_MODE == cipherMode){ECPublicKey keyObj = (ECPublicKey)this.toPubKey(key);ECDomainParameters domainParam = this.getDomainParam(keyObj);ECKeyParameters keyParam = new ECPublicKeyParameters(keyObj.getQ(), domainParam);byte[] initKey = UUID.randomUUID().toString().getBytes(StandardCharsets.UTF_8);sm2Engine.init(true, new ParametersWithRandom(keyParam, this.createRandom(initKey)));}else{ECPrivateKey keyObj = (ECPrivateKey)this.toPriKey(key);ECDomainParameters domainParam = this.getDomainParam(keyObj);ECKeyParameters keyParam = new ECPrivateKeyParameters(keyObj.getD(), domainParam);sm2Engine.init(false, keyParam);} }说明:
- 上面的代码阐述了加解密的核心流程:根据二进制生成秘钥,再基于单独的API计算得到加解密结果,该计算逻辑完全不同于以往的加解密API;
- 通过上述核心代码逻辑,再对比上篇5.非对称加密算法RSA实现,可知SM2本身是支持分段的;
- 通过秘钥二进制反向生成秘钥对象是一个有意思且有点复杂的事情,后面再单独说明;
1.2 SM2生成秘钥及转换实现
-
秘钥生成逻辑
public KeyPair createKey(byte[] initKey) {try{ECGenParameterSpec paramSpec = new ECGenParameterSpec(SM2_VERSION);KeyPairGenerator keyGen = KeyPairGenerator.getInstance(ALGORITHM, this.getProvider());if (null == initKey){initKey = UUID.randomUUID().toString().getBytes(StandardCharsets.UTF_8);}SecureRandom random = this.createRandom(initKey);keyGen.initialize(paramSpec, random);return keyGen.generateKeyPair();}catch (Exception e){throw new EncryptionException("failed to get sm2 key.", e);} } -
公钥、私钥反向生成逻辑
public PublicKey toPubKey(byte[] pubKey) {try{String hexKey = Hex.toHexString(pubKey);KeyFactory kf = KeyFactory.getInstance(ALGORITHM, this.getProvider());if (hexKey.startsWith(STANDARD_HEX_KEY_PREFIX)){return kf.generatePublic(new X509EncodedKeySpec(pubKey));}else{// 获取SM2相关参数X9ECParameters ecParam = GMNamedCurves.getByName(SM2_VERSION);// 将公钥HEX字符串转换为椭圆曲线对应的点ECCurve ecCurve = ecParam.getCurve();ECPoint ecPoint = ecCurve.decodePoint(pubKey);// 椭圆曲线参数规格ECParameterSpec ecSpec = new ECParameterSpec(ecCurve, ecParam.getG(), ecParam.getN(), ecParam.getH());// 将椭圆曲线点转为公钥KEY对象return kf.generatePublic(new ECPublicKeySpec(ecPoint, ecSpec));}}catch (Exception e){throw new EncryptionException("failed to get sm2 pub key.", e);} }public PrivateKey toPriKey(byte[] priKey) {try{String hexKey = Hex.toHexString(priKey);KeyFactory kf = KeyFactory.getInstance(ALGORITHM, this.getProvider());if (hexKey.startsWith(STANDARD_HEX_KEY_PREFIX)){PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(priKey);return kf.generatePrivate(keySpec);}else{// 获取SM2相关参数X9ECParameters ecParam = GMNamedCurves.getByName(SM2_VERSION);ECCurve ecCurve = ecParam.getCurve();// 椭圆曲线参数规格ECParameterSpec ecSpec = new ECParameterSpec(ecCurve, ecParam.getG(), ecParam.getN(), ecParam.getH());// 将私钥HEX字符串转换为16进制的数字值BigInteger bigInteger = new BigInteger(Hex.toHexString(priKey), EncryptionConst.HEX_UNIT);// 将X值转为私钥KEY对象return kf.generatePrivate(new ECPrivateKeySpec(bigInteger, ecSpec));}}catch (Exception e){throw new EncryptionException("failed to get sm2 pri key.", e);} }说明:SM2基于椭圆的原理来加解密,其秘钥生成和解析方式也与其它方式不同。
- SM2支持标准的秘钥生成方式:
BaseSingleSignature sm2 = new Sm2Encryption(); KeyPair keyPair = sm2.createKey(UUID.randomUUID().toString().getBytes(StandardCharsets.UTF_8)); byte[] priKey0 = keyPair.getPrivate().getEncoded(); byte[] pubKey0 = keyPair.getPublic().getEncoded();- SM2支持非标准的秘钥生成方式:
BaseSingleSignature sm2 = new Sm2Encryption(); KeyPair keyPair = sm2.createKey(UUID.randomUUID().toString().getBytes(StandardCharsets.UTF_8)); byte[] priKey1 = ((BCECPrivateKey)keyPair.getPrivate()).getD().toByteArray(); byte[] pubKey1 = ((BCECPublicKey)keyPair.getPublic()).getQ().getEncoded(false); byte[] pubKey2 = ((BCECPublicKey)keyPair.getPublic()).getQ().getEncoded(true);- 上述正文部分的秘钥转换逻辑可以无感兼容上述各种秘钥场景。有兴趣可以看看此算法的单元测试类。PS:网上资料通常只描述了其中一种秘钥生成场景,但是相互间是不兼容的。
-
签名和验签判定逻辑:
public byte[] sign(byte[] data, byte[] key) {try{PrivateKey priKey = this.toPriKey(key);Signature signature = Signature.getInstance(this.getSignatureAlg(), this.getProvider());signature.initSign(priKey);signature.update(data);return signature.sign();}catch (Exception e){throw new EncryptionException("failed to signature.", e);} }public boolean verify(byte[] data, byte[] key, byte[] sign) {try{PublicKey pubKey = this.toPubKey(key);Signature signature = Signature.getInstance(this.getSignatureAlg(), this.getProvider());signature.initVerify(pubKey);signature.update(data);return signature.verify(sign);}catch (Exception e){throw new EncryptionException("failed to verify signature.", e);} } -
SM2加密批量验证逻辑
@Test public void encrypt() {int[] encLengths = {256};super.encrypt(encLengths); }@Test public void testEncryptAndSign() {String initKey = UUID.randomUUID() + new String(RandomUtils.nextBytes(5000), StandardCharsets.UTF_8);int[] encLengths = {256};BaseSingleSignature encryption = new Sm2Encryption();for (int encLen : encLengths){encryption.setEncryptLen(encLen);KeyPair keyPair = encryption.createKey(initKey.getBytes(StandardCharsets.UTF_8));super.testEncryptAndSign(encryption, keyPair.getPrivate().getEncoded(), keyPair.getPublic().getEncoded());} }说明:
- SM2可以不用设置加密长度,因为默认只有一个,同理我们也无需关心其填充算法;
- 通过单元测试对比RSA算法可知,SM2由于秘钥非常短,其秘钥生成和加解密效率明显高于RSA;
2. 总结:
- 基于
BouncyCastle的SM2由于其算法独特性,与其它的算法实现差异加大,但是在实际使用时,由于其秘钥非常短,在核心的加解密执行效率上是有一定优势的; - SM2支持多种方式的秘钥生成,本开源组件较好地解决了秘钥不同方式生成的兼容问题;
- SM2算法相对来说还比较新,在有些
秘改(国密改造)场景时,还无法做到。因为大部分开源组件只支持标准协议,一般支持p256v1非对称加密,但是不支持sm2p256v1,国人仍需努力。
相关文章:
6.开源非对称加密算法SM2实现
6.开源非对称加密算法SM2实现 前期内容导读: 开源加解密RSA/AES/SHA1/PGP/SM2/SM3/SM4介绍开源AES/SM4/3DES对称加密算法介绍及其实现开源AES/SM4/3DES对称加密算法的验证实现开源非对称加密算法RSA/SM2实现及其应用开源非对称加密算法RSA实现 1. 开源组件 非对称秘…...
Toolformer and Tool Learning(LLMs如何使用工具)
大模型的能力让学术和工业界都对通用人工智能的未来充满幻想,在前一篇博文中已经粗略介绍, Augmented Language Models(增强语言模型) ALM的两大思路是推理和工具,本篇博文整理两篇关于Toolformer或Tool Learning的论…...
029:Mapbox GL绘制铁路黑白交替的线段
第029个 点击查看专栏目录 本示例的目的是介绍演示如何在vue+mapbox中加载数据显示铁路标识的那种黑白交替的线段。 直接复制下面的 vue+mapbox源代码,操作2分钟即可运行实现效果 文章目录 示例效果配置方式示例源代码(共94行)相关API参考:专栏目标示例效果 配置方式 1)…...
结对编程 --- 大部分程序员喜欢的编程方式
一、介绍 结对编程起源时间可以追溯到 1990 年代早期。这种编程方法最初由 Jim Highsmith 和 Alistair Cockburn 等人提出。后来,Kent Beck 和 Ward Cunningham 等人将其发展成为一种敏捷开发方法,被称为“极限编程”(Extreme Programming&am…...
kubernetes-informer机制
一、概念 informer 是 client-go 中的核心工具包,在kubernetes中,各个组件通过HTTP协议跟 API Server 进行通信。如果各组件每次都直接和API Server 进行交互,会给API Server 和ETCD造成非常大的压力。在不依赖任何中间件的情况下࿰…...
LeetCode 2451. Odd String Difference【字符串,哈希表】简单
本文属于「征服LeetCode」系列文章之一,这一系列正式开始于2021/08/12。由于LeetCode上部分题目有锁,本系列将至少持续到刷完所有无锁题之日为止;由于LeetCode还在不断地创建新题,本系列的终止日期可能是永远。在这一系列刷题文章…...
切片工具tippecanoe的全网最详细的解释
1.下载和安装 tippecanoe工具是mapbox官方提供的一个服务端切片工具,因此它是运行在服务器上的,它比较友好的支持mac和linux机器。对于windows来讲,就比较麻烦了。 首先对于mac系统,你只需配置好自己的homebrew,保证homebrew能够正常下载东西。 然后只需要一个命令: …...
Linux系统初始化命令的备忘单,Linux运维工程师收藏!
在管理和维护Linux系统时,有一些常用的命令可以帮助您进行系统初始化和配置。这些命令涵盖了各种任务,包括系统设置、用户管理、软件安装和网络配置等。 本文将为您提供一个Linux系统初始化命令的备忘单,以便在需要时方便查阅和使用。 系统设…...
五月最近一次面试,被阿里P8测开虐惨了...
都说金三银四涨薪季,我是着急忙慌的准备简历——5年软件测试经验,可独立测试大型产品项目,熟悉项目测试流程...薪资要求?5年测试经验起码能要个20K吧 我加班肝了一页半简历,投出去一周,面试电话倒是不少&a…...
工业机器视觉缺陷检测工作小结
工业机器视觉检测工作小结 (因为网上没有很系统的讲义和文档,都是零零散散的,因此,我自己尝试着总结一下、仅供参考) 你想知道的大概率在这都可以找到、相机的了解镜头的了解光源的了解传统算法DL深度学习方法 &#…...
技术笔记:默默耕耘,赢得铁粉的秘密策略!
目录 第一步:真实实践,价值分享第二步:高质量文章的撰写第三步:积极互动,回复评论和留言第四步:定期更新和持续学习第五步:参与技术社区第六步:社区问答和问题解答总结 导语…...
回收站中怎么找回误删除的文件?这几种方法很实用
当我们在电脑上操作文件的时候,难免会有不小心删除文件的情况发生。这个时候,我们可以打开回收站来找回误删除的文件。但是,有时候我们也会误将回收站清空。那么,该怎样才能找回已经误删除的文件呢?在这里提供了回收站…...
Gateway网关参数进行验签POST 包含requestbody 请求体封装
Gateway网关自定义拦截器的不可重复读取数据 特别注意一点, 因为在网关层 拿出 request 流之后,必须重写getbody()方法把所有的参数放进去,否则后面转发的请求无法接收到任何数据, 坑,巨坑,因为版本问题网上很多都不能兼容, 我的springboot环境 依赖包 <parent><gr…...
【Netty】字节缓冲区 ByteBuf (六)(上)
文章目录 前言一、ByteBuf类二、ByteBuffer 实现原理2.1 ByteBuffer 写入模式2.2 ByteBuffer 读取模式2.3 ByteBuffer 写入模式切换为读取模式2.4 clear() 与 compact() 方法2.5 ByteBuffer 使用案例 总结 前言 回顾Netty系列文章: Netty 概述(一&…...
Python - 面向对象编程 - 实例方法、静态方法、类方法
实例方法 在类中定义的方法默认都是实例方法,前面几篇文章已经大量使用到实例方法 实例方法栗子 class PoloBlog:def __init__(self, name, age):print("自动调用构造方法")self.name nameself.age agedef test(self):print("一个实例方法&…...
性能测试——基本性能监控系统使用
这里写目录标题 一、基本性能监控系统组成二、环境搭建1、准备数据文件 type.db collectd.conf2、启动InfluxDB3、启动grafana4、启动collectd5、Grafana中配置数据源 一、基本性能监控系统组成 Collectd InfluxdDB Grafana Collectd 是一个守护(daemon)进程,用来…...
JavaCollection集合
5 Collection集合 5.1 Collection集合概述 是单列集合的顶层接口,它表示一组对象,这些对象也称Collection元素JDK不提供此接口的直接实现,它提供更具体的子接口(Set 和 List)实现package ceshi;import java.util.AbstractCollection; import java.util.ArrayList; import…...
C++中string的用法
博主简介:Hello大家好呀,我是陈童学,一个与你一样正在慢慢前行的人。 博主主页:陈童学哦 所属专栏:CSTL 前言:Hello各位小伙伴们好!欢迎来到本专栏CSTL的学习,本专栏旨在帮助大家了解…...
目标检测YOLO实战应用案例100讲-基于深度学习的交通场景多尺度目标检测算法研究与应用
目录 基于深度学习的交通目标检测算法研究 传统的目标检测算法 基于深度学习的目标检测算法 </...
面试:vue事件绑定修饰符
stop - 调用 event.stopPropagation()。 prevent - 调用 event.preventDefault()。 trim 自动过滤用户输入的首尾空格 number 将输出字符串转为Number类型 enter 回车键 capture - 添加事件侦听器时使用 capture 模式。 self - 只当事件是从侦听器绑定的元素本身触发时才触发…...
铭豹扩展坞 USB转网口 突然无法识别解决方法
当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…...
模型参数、模型存储精度、参数与显存
模型参数量衡量单位 M:百万(Million) B:十亿(Billion) 1 B 1000 M 1B 1000M 1B1000M 参数存储精度 模型参数是固定的,但是一个参数所表示多少字节不一定,需要看这个参数以什么…...
相机从app启动流程
一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...
c#开发AI模型对话
AI模型 前面已经介绍了一般AI模型本地部署,直接调用现成的模型数据。这里主要讲述讲接口集成到我们自己的程序中使用方式。 微软提供了ML.NET来开发和使用AI模型,但是目前国内可能使用不多,至少实践例子很少看见。开发训练模型就不介绍了&am…...
是否存在路径(FIFOBB算法)
题目描述 一个具有 n 个顶点e条边的无向图,该图顶点的编号依次为0到n-1且不存在顶点与自身相连的边。请使用FIFOBB算法编写程序,确定是否存在从顶点 source到顶点 destination的路径。 输入 第一行两个整数,分别表示n 和 e 的值(1…...
均衡后的SNRSINR
本文主要摘自参考文献中的前两篇,相关文献中经常会出现MIMO检测后的SINR不过一直没有找到相关数学推到过程,其中文献[1]中给出了相关原理在此仅做记录。 1. 系统模型 复信道模型 n t n_t nt 根发送天线, n r n_r nr 根接收天线的 MIMO 系…...
C++.OpenGL (20/64)混合(Blending)
混合(Blending) 透明效果核心原理 #mermaid-svg-SWG0UzVfJms7Sm3e {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-icon{fill:#552222;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-text{fill…...
华为OD最新机试真题-数组组成的最小数字-OD统一考试(B卷)
题目描述 给定一个整型数组,请从该数组中选择3个元素 组成最小数字并输出 (如果数组长度小于3,则选择数组中所有元素来组成最小数字)。 输入描述 行用半角逗号分割的字符串记录的整型数组,0<数组长度<= 100,0<整数的取值范围<= 10000。 输出描述 由3个元素组成…...
【安全篇】金刚不坏之身:整合 Spring Security + JWT 实现无状态认证与授权
摘要 本文是《Spring Boot 实战派》系列的第四篇。我们将直面所有 Web 应用都无法回避的核心问题:安全。文章将详细阐述认证(Authentication) 与授权(Authorization的核心概念,对比传统 Session-Cookie 与现代 JWT(JS…...
用神经网络读懂你的“心情”:揭秘情绪识别系统背后的AI魔法
用神经网络读懂你的“心情”:揭秘情绪识别系统背后的AI魔法 大家好,我是Echo_Wish。最近刷短视频、看直播,有没有发现,越来越多的应用都开始“懂你”了——它们能感知你的情绪,推荐更合适的内容,甚至帮客服识别用户情绪,提升服务体验。这背后,神经网络在悄悄发力,撑起…...
