Java 国密 SM4 加密工具类实战
前面给大家分享了企业级敏感数据脱敏工具类,其核心作用是在日志打印、接口返回、页面展示等场景中,实现敏感信息的 隐藏展示,避免隐私数据直接暴露,但必须明确的是: 脱敏≠加密 ,二者不可混淆、不可替代。
在实际企业开发中,对于需要落地存储、跨系统传输的核心敏感数据(比如用户身份证号、手机号、银行卡号,以及系统密码、核心密钥等),仅靠脱敏远远不够,必须采用符合合规要求的强加密算法进行全流程保护,才能从根本上防范数据泄露、篡改等安全风险。
因此,国密 SM4 工具类,整合了 Hutool 极简封装实现、BouncyCastle 原生底层实现,以及企业生产环境首选的 SM4-GCM 认证加密模式,全程遵循企业级开发规范,兼容 JDK8,可直接复制到项目中使用,既满足数据安全需求,也契合国产化、合规化要求。
在 2026 年至今,SM4 已成为敏感数据加密的 "国标标配":金融 / 政务 / 国企 / 关基全面普及,信创 100% 覆盖,市场高速增长,安全与性能双优,合规刚需不可替代。
一、应用背景
1. 为什么必须使用国密?
随着 《网络安全法》《数据安全法》《个人信息保护法》(PIPL) 的全面实施,金融、政务、医疗、国企及及关基项目的敏感数据保护,已从 "可选优化" 升级为 "合规红线",明确要求:
- 全面禁止使用 DES/3DES、MD5、SHA-1等弱算法,杜绝数据泄露风险;
- 核心场景优先用国密替代 AES/RSA/SHA,降低境外技术依赖;
- 关基 / 等保系统强制要求采用国密算法(SM2 非对称加密、SM3 哈希摘要、SM4 对称加密),实现敏感数据全生命周期的国产化安全防护。
而 SM4 作为国家密码管理局发布的官方对称加密标准,是国密体系中应用最广泛、适配场景最全面的算法。既能满足企业级数据加密的性能需求,又能完美契合国产化替代、合规审计、等保测评的全部要求,是当前敏感数据加密的首选方案。
2. 脱敏 vs 加密
- 脱敏:展示用、不可逆、用于页面 / 日志
- 加密:存储用、可逆、用于数据库 / 传输
企业安全体系 = 脱敏 + 加密 + 权限控制
3. SM4 是什么?
- 对称分组密码算法
- 固定密钥长度 128 位(16 字节)
- 分组长度 128 位
- 安全、高效、国产化、合规
二、应用场景
在以下场景必须使用 SM4 加密:
- 用户身份证号、手机号存储数据库
- 银行卡号、交易金额、密钥等敏感信息落库
- 内部接口敏感数据传输加密
- 配置文件中的密钥、账号加密
- 等保测评、合规审计
- 金融、政务、国企、医疗项目强制要求
三、SM4 国密工具类说明
- 两套实现:Hutool(极简) + BouncyCastle(原生)
- 支持 ECB 模式(快速开发)
- 支持 GCM 模式(企业安全推荐)
- Base64、16 进制编码
- 兼容 JDK8
- 无 Bug、经过测试、可直接复制使用
- 结构清晰、注释完整、符合企业规范
四、Maven 依赖
java
<!-- Hutool -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-crypto</artifactId>
<version>5.8.20</version>
</dependency>
<!-- BouncyCastle -->
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.70</version>
</dependency>
五、完整 SM4 国密工具类
java
import cn.hutool.crypto.SmUtil;
import cn.hutool.crypto.symmetric.SM4;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import javax.crypto.Cipher;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.SecureRandom;
import java.security.Security;
import java.util.Base64;
/**
* 国密 SM4 对称加密工具类
* 应用场景:敏感数据(手机号/身份证/银行卡)存储加密、传输加密、等保合规、国产化加密
* 支持算法模式:ECB / GCM(GCM为生产环境推荐)
* 依赖:Hutool-crypto + BouncyCastle
* 兼容 JDK8+
*
*/
public class Sm4Utils {
/**
* 静态代码块:注册 BouncyCastle 密码提供者
* 作用:让 JDK 支持国密 SM4 算法
*/
static {
Security.addProvider(new BouncyCastleProvider());
}
// ==================== 1. Hutool 封装版(简洁易用,推荐快速开发)=====================
/**
* SM4 加密(Hutool 实现)
*
* @param key 密钥,SM4 固定 16 字节(128位)
* @param data 明文字符串(需要加密的原始数据)
* @return 加密后的十六进制字符串
*/
public static String encrypt(byte[] key, String data) {
SM4 sm4 = SmUtil.sm4(key);
return sm4.encryptHex(data);
}
/**
* SM4 解密(Hutool 实现)
*
* @param key 密钥(与加密密钥一致)
* @param cipherText 加密后的十六进制字符串
* @return 解密后的原始明文字符串
*/
public static String decrypt(byte[] key, String cipherText) {
SM4 sm4 = SmUtil.sm4(key);
return sm4.decryptStr(cipherText);
}
// ==================== 2. BouncyCastle 原生 ECB 模式(基础加密)=====================
/**
* SM4-ECB 加密(原生实现)
* 说明:ECB 模式简单,无 IV向量,适合内部系统/测试环境
*
* @param key 密钥 16字节
* @param data 明文字节数组
* @return 加密后的字节数组
* @throws Exception 加密异常
*/
public static byte[] encryptECB(byte[] key, byte[] data) throws Exception {
Cipher cipher = Cipher.getInstance("SM4/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "SM4"));
return cipher.doFinal(data);
}
/**
* SM4-ECB 解密(原生实现)
*
* @param key 密钥 16字节
* @param cipherData 加密后的字节数组
* @return 解密后的原始字节数组
* @throws Exception 解密异常
*/
public static byte[] decryptECB(byte[] key, byte[] cipherData) throws Exception {
Cipher cipher = Cipher.getInstance("SM4/ECB/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key, "SM4"));
return cipher.doFinal(cipherData);
}
// ==================== 3. SM4-GCM 模式(企业生产环境最高安全级别)=====================
/**
* SM4-GCM 加密(带认证加密,防篡改、防伪造、防重放)
* 说明:GCM 是目前最安全的对称加密模式,等保/金融/政务项目强制使用
*
* @param key 密钥 16字节
* @param data 明文字节数组
* @return 加密结果格式:IVBase64:CipherBase64
* @throws Exception 加密异常
*/
public static String encryptGCM(byte[] key, byte[] data) throws Exception {
Cipher cipher = Cipher.getInstance("SM4/GCM/NoPadding", "BC");
SecretKeySpec keySpec = new SecretKeySpec(key, "SM4");
// GCM 标准推荐使用 12字节 随机IV(安全性最高)
byte[] iv = new byte[12];
new SecureRandom().nextBytes(iv);
// 初始化 GCM 参数
GCMParameterSpec gcmSpec = new GCMParameterSpec(128, iv);
cipher.init(Cipher.ENCRYPT_MODE, keySpec, gcmSpec);
// 执行加密
byte[] cipherBytes = cipher.doFinal(data);
// 拼接结果:IV + 密文(Base64格式,方便存储传输)
String ivStr = Base64.getEncoder().encodeToString(iv);
String cipherStr = Base64.getEncoder().encodeToString(cipherBytes);
return ivStr + ":" + cipherStr;
}
/**
* SM4-GCM 解密(对应上方 GCM 加密)
*
* @param key 密钥 16字节
* @param encryptData 加密字符串(格式:IVBase64:CipherBase64)
* @return 解密后的原始字节数组
* @throws Exception 解密异常
*/
public static byte[] decryptGCM(byte[] key, String encryptData) throws Exception {
// 拆分 IV 和 密文
String[] arr = encryptData.split(":");
byte[] iv = Base64.getDecoder().decode(arr[0]);
byte[] cipherBytes = Base64.getDecoder().decode(arr[1]);
// 初始化解密器
Cipher cipher = Cipher.getInstance("SM4/GCM/NoPadding", "BC");
SecretKeySpec keySpec = new SecretKeySpec(key, "SM4");
GCMParameterSpec gcmSpec = new GCMParameterSpec(128, iv);
cipher.init(Cipher.DECRYPT_MODE, keySpec, gcmSpec);
// 执行解密
return cipher.doFinal(cipherBytes);
}
// ==================== 测试主方法=====================
public static void main(String[] args) throws Exception {
// 测试数据:敏感信息示例
String originalData = "13800138000";
System.out.println("原始数据:" + originalData);
// ================== 测试 Hutool SM4 ==================
// Hutool方式 生成 SM4 安全密钥(固定 16 字节)
byte[] sm4KeyHutool = SmUtil.sm4().getSecretKey().getEncoded();
String encryptResult = encrypt(sm4KeyHutool, originalData);
String decryptResult = decrypt(sm4KeyHutool, encryptResult);
System.out.println("\n====== Hutool SM4 加解密 ======");
System.out.println("Hutool 加密结果:" + encryptResult);
System.out.println("Hutool 解密结果:" + decryptResult);
// ================== 测试 SM4-GCM ==================
// 生成 SM4 安全密钥(固定 16 字节)
byte[] sm4Key = new byte[16];
new SecureRandom().nextBytes(sm4Key);
String gcmEncrypt = encryptGCM(sm4Key, originalData.getBytes());
byte[] gcmDecrypt = decryptGCM(sm4Key, gcmEncrypt);
System.out.println("\n====== SM4-GCM 加解密(生产推荐)======");
System.out.println("GCM 加密结果:" + gcmEncrypt);
System.out.println("GCM 解密结果:" + new String(gcmDecrypt));
}
}
六、模式说明
- ECB 模式
- 简单、快速
- 适合内部系统、测试环境
- 不适合极高安全要求场景
- GCM 模式(生产环境首选)
- 带认证加密
- 防篡改、防重放、防伪造
- 等保、金融、政务项目强制使用
七、测试结果
java
原始数据:13800138000
====== Hutool SM4 加解密 ======
Hutool 加密结果:e6d40a71bd384d207da4ba99efe0ad13
Hutool 解密结果:13800138000
====== SM4-GCM 加解密(生产推荐)======
GCM 加密结果:Awb53K/OrL1NvX5m:7rULJDC9M6Cl9JsCG3KU1YN4iIARpfZIEV3T
GCM 解密结果:13800138000
八、安全规范
- SM4 密钥必须 16 字节(128bit)
- 密钥不能硬编码在代码中(使用配置中心 / 密钥管理系统)
- GCM 模式每次必须生成随机 IV
- 敏感数据必须加密后入库
- 加密工具类必须做异常捕获、日志记录
九、总结
SM4 国密加密是当前企业级项目中,敏感数据加密存储、网络传输的标准化落地方案,完全契合国家商用密码管理政策、网络安全等级保护规范以及《个人信息保护法》合规要求。
本文的工具类兼顾不同业务场景适配需求,同时提供三种实现方式:
- Hutool 极简版:上手简单、开发高效,适合快速业务开发;
- ECB 原生实现版:兼容性强,可无缝适配老旧历史系统改造;
- GCM 认证加密版:具备防篡改、防重放能力,安全等级更高,为生产环境首选方案。