基于hutools的国密SM2、3、4
文章目录
- 前言
- 一. 代码
前言
最近还要深度研究hutools底层实现,一定要搞透澈,本章将会是持续更新
参考资料:
Java代码实现SM2算法以及注意点总结(踩坑记录)
国密算法工具Smutil
一. 代码
import cn.hutool.core.util.HexUtil;
import cn.hutool.crypto.ECKeyUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.SmUtil;
import cn.hutool.crypto.asymmetric.SM2;
import cn.hutool.crypto.symmetric.SM4;
import lombok.extern.slf4j.Slf4j;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;import java.nio.charset.StandardCharsets;
import java.security.KeyPair;/*** @author YuanJie* @date 2024/8/6 上午8:44* 加密方式* 加密方式里边,有两种 一种是 C1C3C2另一种是C1C2C3,* 这两种加密方式不同,当时找的资料说是,旧版本的标准上,* 使用的是C1C2C3,但是后续应该是更新过,使用的是C1C3C2,* 其他语言,比如Python或者Golang或者C的实现大多直接就是C1C3C2的,* 但是如果java中使用的bouncycastle的包,默认使用的是C1C2C3,* 就会发生与其他语言的加密结果不能相互解密的情况,但是可能你跟其他人的Java系统加解密又没有问题。* <p>* 导出* Java生成的密钥,在导出的时候,最好使用 PrivateKey.getD().toByteArray() 和 PublicKey.getQ().getEncoded() 导出密钥,然后再转成Base64或者Hex给其他系统;* <p>* 导入* 导入的时候,请使用我上边的代码转换成对应的公钥或者私钥的对象,* 这里有另一个容易出错的地方,在私钥byte[]转私钥对象的时候,* 有些人会使用new BigInteger(byte[])这个方法将byte[]转为BigInteger,* 然后调用 keyFactory.generatePrivate(new ECPrivateKeySpec(BigInteger, ECParameterSpec)),* 但是实测这样在一些情况下会报错,这个时间长了记不清具体原因了,好像是因为第一位为负数的情况下会报错,* 我的方法是把byte[]转为Hex,然后再使用new BigInteger(hexStr, int)这种方式转为BigInteger,这个需要注意。* <p>* 公钥压缩* publicKey.getQ().getEncoded()这个方法,* 有一个boolean参数,控制输出的密钥是否为压缩后的密钥,* 输出内容转为Hex之后,02和03开头的为压缩后的密钥,04表示未经压缩的密钥。* Java里边压缩为压缩的调用同一个方法就能转为公钥对象,但是其他语言的目前不清楚,所以导出的时候,最好标注一下压缩或者未压缩。* <p>* Sm2签名时,有一个userId的概念,这个东西一般直接用CipherParameters对象是带不进去的,* 如果没有,默认是 Hex.decodeStrict(“31323334353637383132333435363738”) ,* 也就是1234567812345678的Ascii值,如果要使用自定义的userId,则需要使用ParametersWithID这个对象调用Signer的init,* 这个对象可以传入一个CipherParameters,然后再传入一个userId,可以把制定的userId带进去。* <p>* 签名验签RS* 我们平常接触的算法,一般我们调用加解密算法只返回一个值,* 但是Sm2算法,签名其实是有两个值,一个R,一个S,* 两个值构成一个签名结果,Java中bouncycastle的返回虽然也是一个值,* 但是大概看了一下算法的实现代码,其实得出的结果也是两个值,* 一个R,一个S,然后通过一个方法拼接成一个值(不确定这个方法的转换方式是不是有标准的)。* 在我们与C程序一块测试的时候,他们反馈了这个问题,* 然后我对着bouncycastle包内的org.bouncycastle.crypto.signers.SM2Signer类,* 摘出来了R、S和单一返回值的转换代码,已经提取到上边的代码里,可以直接使用。*/
@Configuration
@Slf4j
public class NationalSecretsUtils {public static String privateKey2;public static String publicKey2;public static String secretKey4;public NationalSecretsUtils(@Value("${sm2.privateKey}") String privateKey2,@Value("${sm2.publicKey}") String publicKey2,@Value("${sm4.secretKey}") String secretKey4) {NationalSecretsUtils.privateKey2 = privateKey2;NationalSecretsUtils.publicKey2 = publicKey2;NationalSecretsUtils.secretKey4 = secretKey4;}public static void main(String[] args) {KeyPair keyPair = SecureUtil.generateKeyPair("SM2");// 2. 获取公私钥//这里公钥不压缩 公钥的第一个字节用于表示是否压缩 可以不要 65字节变64字节byte[] publicKey = ((BCECPublicKey) keyPair.getPublic()).getQ().getEncoded(false);byte[] privateKey = ((BCECPrivateKey) keyPair.getPrivate()).getD().toByteArray();String sm2pub = HexUtil.encodeHexStr(publicKey);String sm2pri = HexUtil.encodeHexStr(privateKey);NationalSecretsUtils.publicKey2 = sm2pub;NationalSecretsUtils.privateKey2 = sm2pri;NationalSecretsUtils.secretKey4 = HexUtil.encodeHexStr(SecureUtil.generateKey("SM4").getEncoded());log.info("sm2公钥:{}", sm2pub);log.info("sm2私钥:{}", sm2pri);log.info("sm4密钥:{}", NationalSecretsUtils.secretKey4);// 测试sm2加解密log.info("sm2签名:{}", HexUtil.encodeHexStr(generateSM2Sign("我是sm2数据")));log.info("sm2验证:{}", verifySM2Sign("我是sm2数据", generateSM2Sign("我是sm2数据")));// 测试sm4加解密log.info("sm4加密:{}", HexUtil.encodeHexStr(generateSM4Sign("我是sm4数据")));log.info("sm4解密:{}", decryptSM4Sign(generateSM4Sign("我是sm4数据")));// 测试sm3哈希算法log.info("sm3哈希算法:{}", generateSM3Sign("我是sm3数据"));log.info("sm3验证:{}", verifySM3Sign("我是sm3数据", generateSM3Sign("我是sm3数据")));}/*** SM2签名 使用私钥D值签名* 默认C1C3C2** @param text* @return*/public static byte[] generateSM2Sign(String text) {SM2 sm2 = new SM2(privateKey2, null, null);sm2.usePlainEncoding();return sm2.sign(text.getBytes(StandardCharsets.UTF_8), null);}/*** SM2验证 使用公钥Q值验证签名** @param text* @param sign* @return*/public static boolean verifySM2Sign(String text, byte[] sign) {SM2 sm2 = new SM2(null, ECKeyUtil.toSm2PublicParams(publicKey2));sm2.usePlainEncoding();return sm2.verify(text.getBytes(StandardCharsets.UTF_8), sign);}/*** SM3 哈希算法 3是能够计算出256比特的散列值的单向散列函数,主要用于数字签名和消息认证码。*/public static String generateSM3Sign(String text) {return SmUtil.sm3(text);}/*** SM3验证** @param text* @param sign* @return*/public static boolean verifySM3Sign(String text, String sign) {return SmUtil.sm3(text).equals(sign);}/*** SM4 是一种对称加密算法,它使用128位密钥,使用分组密码模式,使用CBC模式加密。* SM4加密*/public static String generateSM4Sign(String text) {SM4 sm4 = SmUtil.sm4(HexUtil.decodeHex(secretKey4));return sm4.encryptHex(text);}/*** SM4解密*/public static String decryptSM4Sign(String text) {SM4 sm4 = SmUtil.sm4(HexUtil.decodeHex(secretKey4));return sm4.decryptStr(text, StandardCharsets.UTF_8);}
}
相关文章:
基于hutools的国密SM2、3、4
文章目录 前言一. 代码 前言 最近还要深度研究hutools底层实现,一定要搞透澈,本章将会是持续更新 参考资料: Java代码实现SM2算法以及注意点总结(踩坑记录) 国密算法工具Smutil 一. 代码 import cn.hutool.core.uti…...

进程的等待(非阻塞轮询+阻塞)和替换控制详解
引言 在Linux系统中,进程管理是核心功能之一。理解进程的创建、执行和终止是系统编程中的基础。本文将深入探讨Linux中的进程控制机制,包括进程的生命周期、父子进程的交互、以及进程状态的管理 1. 进程创建:fork()函数 在Linux操作系统中…...

24/8/6算法笔记 支持向量机
支持向量机(Support Vector Machine, SVM)是一种监督学习算法,主要用于分类和回归任务。它基于统计学习理论中的结构风险最小化原理,通过找到数据点之间的最优边界来实现模型的泛化能力。 import numpy as np import matplotlib.…...
测试用例等级划分
基本等级(Level 1或P0):这类用例设计系统基本功能,执行失败会导致多处重要功能无法运行。例如,单表维护中的增加功能、最平常的业务使用等,这些是发生概率较高的功能用例。这类用例在每一…...
打造Perl编译器前端:自定义语言处理的魔法
打造Perl编译器前端:自定义语言处理的魔法 Perl是一种强大而灵活的编程语言,它提供了丰富的文本处理能力,使其成为实现自定义编译器前端的理想选择。编译器前端通常负责源代码的词法分析、语法分析和语义分析。本文将详细介绍如何在Perl中实…...

Visual Studio 和 Visual Studio Code 的比较与应用偏向
Visual Studio 和 Visual Studio Code(VS Code)是微软开发的两个不同的开发工具,各有特点和优势,适用于不同的开发需求。下面是详细的比较和在实际应用中的偏向。 功能和特性 Visual Studio 完整的IDE:支持多种编程…...

Python打开JSON/CSV文件的正确方式(针对UnicodeDecodeError)
前言 我们在使用python的过程中,经常需要它完成一些数据处理的工作,其中尤以json/csv文件为常见。今天,博主针对UnicodeDecodeError异常进行试验,因为这个是新手最容易犯错的地方。 Q:如何应对 UnicodeDecodeError 读…...
深入解析TikTok广告开户白名单:规范与申请指南
在TikTok的广告平台上,白名单(Whitelist)系统作为一种重要的审核和管理机制,对广告账户的开设与运营起着至关重要的作用。 一、什么是TikTok广告开户白名单? 白名单的定义 白名单是一种预先批准的账户或广告内容列表…...

CSS技巧专栏:一日一例 19 -纯CSS实现超酷的水晶按钮特效
CSS技巧专栏:一日一例 19 -纯CSS实现超酷的水晶按钮特效 今天给大家分享一个纯CSS按钮水晶按钮,效果很赞,希望对大家有所帮助。 本例图片 案例分析 这个按钮看起来效果很赞,我们分析一下它由几个层组成: 1. 按钮本体:渐变层+按钮文字 2.用before伪元素实现高光层+内…...

ArcGIS基础:基于数据图框实现地理坐标系下不同投影转换的可视化效果
ArcGIS默认以第一次加载数据的坐标系决定整个工程的坐标系 可以通过改变数据框的投影坐标系,对地理数据进行快速投影变换,以可视化展示不同投影坐标系下的地理数据形状和形态 对数据框坐标系的改变,只是针对的显示参数的改变,并…...
⚡4. Kubernetes核心资源管理操作实战
文章目录 kubectl [command] [TYPE] [NAME] [flags]kubectl run 资源名称 --image镜像名称 --port端口号kubectl create -f 配置文件名称.yaml kubectl apply -f 配置文件名称.yaml快速编写yaml文件,通过命令导出新的yaml文件Kubernetes常见资源类型和缩写 kubectl …...
【Wireshark 抓 CAN 总线】Wireshark 抓取 CAN 总线数据的实现思路
最近看到一个帖子 Wireshark 对接 Windows 系统命名管道,抓取数据 我突然想到一个很有意思的方式 你没看错 用 Wireshark 来抓取 CAN 总线数据 【其实 Wireshark 上有 CAN 总线的的解码器,不信你可以在表达式栏打 can 试下,是有这个解码器的】…...

Linux网络编程3
并发服务器 1.TCP多进程并发服务器 服务器端: 客户端: 2.TCP多线程服务器 服务器端: 客户机端: 需要学习的函数还有 1. send() 函数 send() 函数用于在套接字上发送数据。它是网络编程中发送数据到对端的主要函数之一。 函数…...

gitlab 服务器安装
阿里云盘快传 百度链接 链接:https://pan.baidu.com/s/1Gn5bWHi45Dcpe1RH1S06dw 提取码:yai2 然后就是有一台服务器 cd /mkdir gitlab上传下载好的东西rpm -ivh gitlab-ce-10.8.4-ce.0.el7.x86_64.rpm 这里可以tab提示vim /etc/gitlab/gitlab.rb我建议…...

【pytorch】全连接网络简单二次函数拟合
下面是一个使用PyTorch实现全连接网络来拟合简单二次函数 y x 2 y x^2 yx2 的示例。我们将创建一个简单的神经网络,定义损失函数和优化器,并进行训练。 下面是完整的代码示例: import torch import torch.nn as nn import torch.optim …...
git提交到本地仓库了,怎么撤回
如果你想要撤回已经提交到本地仓库的更改,可以使用以下一些Git命令: 1. **撤回最后一次提交** (不保留更改): - git reset --hard HEAD~1:这会撤销最后一次提交,并且所有的更改都会丢失。 2. **撤回最后一次提交** (保留更改…...

lua学习(1)
vscode打开c或者lua文件 插件显示禁用,怎么开启插件。 1. lua 字符串 单个引号和双引号都可变量的定义默认是全局的删除一个变量将其赋值为nil即可 如: bnilnil还可以对表中的数据进行删除,也可删除一个表只要变量不是nil,变…...

SQL报错注入之updatexml
目录 1.updatexml报错原理 2.判断是否有注入点 我们在地址栏中输入?id1 我们在地址栏中输入?id1-- 3.updatexml报错注入 3.1爆库名 3.2爆表名 3.3爆字段名 3.4爆数据 1.updatexml报错原理 updatexml(xml_doument,XPath_string,new_value) 第一个参数:XML…...
单元测试的重要性
单元测试和测试驱动开发(TDD)是软件开发中的关键实践,它们有助于提高代码的质量和可维护性。以下是对单元测试和TDD的深入分析,以及如何使用Java中的测试框架来提高代码质量的指南。 单元测试的重要性 单元测试是针对程序中最小…...
mysql线上查询数据注意锁表问题
在数据库中,锁定是用来控制多个事务并发访问相同数据时的一种机制。正确的锁定机制可以保证数据的一致性和完整性,但如果不当使用,也可能导致阻塞和死锁,特别是在高并发环境中。长时间的锁等待不仅会影响当前的事务,还…...
《Playwright:微软的自动化测试工具详解》
Playwright 简介:声明内容来自网络,将内容拼接整理出来的文档 Playwright 是微软开发的自动化测试工具,支持 Chrome、Firefox、Safari 等主流浏览器,提供多语言 API(Python、JavaScript、Java、.NET)。它的特点包括&a…...
linux 错误码总结
1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...

Python爬虫(一):爬虫伪装
一、网站防爬机制概述 在当今互联网环境中,具有一定规模或盈利性质的网站几乎都实施了各种防爬措施。这些措施主要分为两大类: 身份验证机制:直接将未经授权的爬虫阻挡在外反爬技术体系:通过各种技术手段增加爬虫获取数据的难度…...

关键领域软件测试的突围之路:如何破解安全与效率的平衡难题
在数字化浪潮席卷全球的今天,软件系统已成为国家关键领域的核心战斗力。不同于普通商业软件,这些承载着国家安全使命的软件系统面临着前所未有的质量挑战——如何在确保绝对安全的前提下,实现高效测试与快速迭代?这一命题正考验着…...
return this;返回的是谁
一个审批系统的示例来演示责任链模式的实现。假设公司需要处理不同金额的采购申请,不同级别的经理有不同的审批权限: // 抽象处理者:审批者 abstract class Approver {protected Approver successor; // 下一个处理者// 设置下一个处理者pub…...

【VLNs篇】07:NavRL—在动态环境中学习安全飞行
项目内容论文标题NavRL: 在动态环境中学习安全飞行 (NavRL: Learning Safe Flight in Dynamic Environments)核心问题解决无人机在包含静态和动态障碍物的复杂环境中进行安全、高效自主导航的挑战,克服传统方法和现有强化学习方法的局限性。核心算法基于近端策略优化…...

LINUX 69 FTP 客服管理系统 man 5 /etc/vsftpd/vsftpd.conf
FTP 客服管理系统 实现kefu123登录,不允许匿名访问,kefu只能访问/data/kefu目录,不能查看其他目录 创建账号密码 useradd kefu echo 123|passwd -stdin kefu [rootcode caozx26420]# echo 123|passwd --stdin kefu 更改用户 kefu 的密码…...

搭建DNS域名解析服务器(正向解析资源文件)
正向解析资源文件 1)准备工作 服务端及客户端都关闭安全软件 [rootlocalhost ~]# systemctl stop firewalld [rootlocalhost ~]# setenforce 0 2)服务端安装软件:bind 1.配置yum源 [rootlocalhost ~]# cat /etc/yum.repos.d/base.repo [Base…...

【C++进阶篇】智能指针
C内存管理终极指南:智能指针从入门到源码剖析 一. 智能指针1.1 auto_ptr1.2 unique_ptr1.3 shared_ptr1.4 make_shared 二. 原理三. shared_ptr循环引用问题三. 线程安全问题四. 内存泄漏4.1 什么是内存泄漏4.2 危害4.3 避免内存泄漏 五. 最后 一. 智能指针 智能指…...

pikachu靶场通关笔记19 SQL注入02-字符型注入(GET)
目录 一、SQL注入 二、字符型SQL注入 三、字符型注入与数字型注入 四、源码分析 五、渗透实战 1、渗透准备 2、SQL注入探测 (1)输入单引号 (2)万能注入语句 3、获取回显列orderby 4、获取数据库名database 5、获取表名…...