基于 Hutool 工具类实现 SM2 加密解密完整实践(附完整代码)

SM2 作为国家密码管理局推荐的非对称加密算法,在金融、政务、物联网等领域有着广泛应用。相较于 RSA 算法,SM2 在安全性、性能和密钥长度上均具备显著优势。本文将基于 Hutool 工具类,从密钥生成、加密解密实现到实际接口调用,完整讲解 SM2 加密解密的落地实践,并提供可直接运行的代码示例。

一、SM2 算法基础认知
在开始编码前,我们先明确 SM2 的核心特性,这对后续理解代码逻辑至关重要:

1.1 SM2 核心优势
高安全性:基于椭圆曲线密码(ECC),256 位密钥长度的安全性等效于 3072 位 RSA 密钥,抗攻击能力更强。
高性能:加密解密速度比 RSA 快数倍,尤其适合资源受限的设备(如嵌入式设备、移动端)。
标准合规:符合《GB/T 32918-2016 信息安全技术 SM2 椭圆曲线公钥密码算法》国家标准,满足国内合规要求。
1.2 关键概念
密钥对:包含公钥(公开,用于加密)和私钥(保密,用于解密),公钥由私钥推导生成。
加密模式:SM2 加密结果有两种格式:
C1C2C3:默认格式,C1(椭圆曲线点)、C2(密文数据)、C3(杂凑值)。
C1C3C2:部分场景使用,调整 C2 和 C3 的顺序,需加密解密双方统一。
数据格式:加密结果通常以十六进制(Hex)字符串形式传输,避免二进制数据传输中的乱码问题。
二、开发环境准备
2.1 依赖引入
本文基于 Hutool 工具类实现 SM2,Hutool 已封装 BouncyCastle(SM2 算法的底层实现库),无需额外引入 BouncyCastle 依赖。

Maven 依赖

<!-- Hutool工具类(包含SM2加密解密) -->
<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.8.25</version> <!-- 建议使用最新稳定版 -->
</dependency>
 
<!-- 阿里巴巴FastJSON(用于JSON处理,可选,可替换为Jackson等) -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.83</version>
</dependency>
 
<!-- Netty(用于字符串工具类,可选,可替换为其他字符串工具) -->
<dependency>
    <groupId>io.netty</groupId>
    <artifactId>netty-common</artifactId>
    <version>4.1.94.Final</version>
</dependency>
Gradle 依赖
implementation 'cn.hutool:hutool-all:5.8.25'
implementation 'com.alibaba:fastjson:1.2.83'
implementation 'io.netty:netty-common:4.1.94.Final'

三、SM2 工具类完整实现
下面是封装好的 SM2 工具类,包含密钥对生成、加密、解密三个核心方法,以及实际接口调用的测试示例。

3.1 工具类代码(SM2Util.java)
四、核心方法详解
4.1 密钥对生成(genC1C3C2KeyPair)
功能:自动生成 SM2 公钥和私钥,返回 Hex 格式的字符串列表。
关键逻辑:
通过new SM2()初始化实例,Hutool 会自动生成符合 SM2 标准的密钥对。
sm2.getQ(false):获取公钥(false表示非压缩格式,包含 04 前缀),通过HexUtil.encodeHexStr转换为 Hex 字符串。
sm2.getDHex():直接获取私钥的 Hex 字符串(256 位)。
使用场景:密钥对通常由服务端生成,公钥分发给客户端 / 第三方,私钥由服务端妥善保管(如存入密钥管理系统 KMS)。
4.2 加密方法(encrypt)
公钥处理:兼容两种公钥格式(带 04 前缀和不带 04 前缀),若公钥长度为 某个值(04 前缀 + 128 位公钥),则去掉前缀后拆分 X 和 Y。
模式设置:根据传入的mode参数设置加密模式(C1C2C3 或 C1C3C2),需与解密端保持一致。
加密结果:Hutool 的encryptHex方法返回的密文含 某个 前缀,此处去掉前缀后返回,减少传输数据量。
4.3 解密方法(decrypt)
私钥处理:通过ECKeyUtil.toSm2PrivateParams将 Hex 格式私钥转换为 BouncyCastle 的私钥对象。
密文前缀:解密时需给密文添加 某个 前缀(与加密时去掉的前缀对应),否则会解密失败。
模式一致性:解密模式必须与加密模式完全一致,否则无法正确解析密文。
五、实际应用注意事项
5.1 密钥安全
禁止硬编码:为了方便测试,将密钥硬编码在代码中,实际项目中需从配置文件(如 application.yml)或密钥管理系统(如阿里云 KMS、华为云 KMS)获取。
私钥保密:私钥是解密的核心,需严格保密,避免泄露。建议采用硬件加密机(HSM)存储私钥,防止被窃取。
定期轮换:为降低密钥泄露风险,建议定期(如 3 个月)轮换密钥对,并及时更新客户端 / 第三方的公钥。
5.2 模式一致性
加密和解密必须使用相同的模式(C1C2C3 或 C1C3C2),否则会出现 “解密失败” 或 “明文乱码” 问题。
若对接第三方系统,需提前确认对方使用的加密模式,避免因模式不匹配导致接口调用失败。
5.3 数据校验
入参校验:加密前需校验公钥和明文是否为空,避免空指针异常。
响应校验:解密前需校验接口返回的密文是否为空,若为空则提示 “接口调用失败”,避免解密时出现异常。
完整性校验:SM2 加密结果中的 C3 是杂凑值,可用于校验数据完整性。若需更严格的校验,可在加密前对明文添加签名(如 SM3 签名)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值