Java 国密 SM4 加密工具类实战(Hutool + BouncyCastle)|企业级数据加密 + 兼容 JDK8

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 加密:

  1. 用户身份证号、手机号存储数据库
  2. 银行卡号、交易金额、密钥等敏感信息落库
  3. 内部接口敏感数据传输加密
  4. 配置文件中的密钥、账号加密
  5. 等保测评、合规审计
  6. 金融、政务、国企、医疗项目强制要求

三、SM4 国密工具类说明

  1. 两套实现:Hutool(极简) + BouncyCastle(原生)
  2. 支持 ECB 模式(快速开发)
  3. 支持 GCM 模式(企业安全推荐)
  4. Base64、16 进制编码
  5. 兼容 JDK8
  6. 无 Bug、经过测试、可直接复制使用
  7. 结构清晰、注释完整、符合企业规范

四、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));
    }

}

六、模式说明

  1. ECB 模式
  • 简单、快速
  • 适合内部系统、测试环境
  • 不适合极高安全要求场景
  1. GCM 模式(生产环境首选
  • 带认证加密
  • 防篡改、防重放、防伪造
  • 等保、金融、政务项目强制使用

七、测试结果

java 复制代码
原始数据:13800138000

====== Hutool SM4 加解密 ======
Hutool 加密结果:e6d40a71bd384d207da4ba99efe0ad13
Hutool 解密结果:13800138000

====== SM4-GCM 加解密(生产推荐)======
GCM 加密结果:Awb53K/OrL1NvX5m:7rULJDC9M6Cl9JsCG3KU1YN4iIARpfZIEV3T
GCM 解密结果:13800138000

八、安全规范

  1. SM4 密钥必须 16 字节(128bit)
  2. 密钥不能硬编码在代码中(使用配置中心 / 密钥管理系统)
  3. GCM 模式每次必须生成随机 IV
  4. 敏感数据必须加密后入库
  5. 加密工具类必须做异常捕获、日志记录

九、总结

SM4 国密加密是当前企业级项目中,敏感数据加密存储、网络传输的标准化落地方案,完全契合国家商用密码管理政策、网络安全等级保护规范以及《个人信息保护法》合规要求。

本文的工具类兼顾不同业务场景适配需求,同时提供三种实现方式:

  • Hutool 极简版:上手简单、开发高效,适合快速业务开发;
  • ECB 原生实现版:兼容性强,可无缝适配老旧历史系统改造;
  • GCM 认证加密版:具备防篡改、防重放能力,安全等级更高,为生产环境首选方案。
相关推荐
庞轩px1 小时前
第8篇:原子类与CAS底层原理——无锁并发的实现
java·cas·乐观锁·aba·无锁编程·自旋
rleS IONS1 小时前
SpringBoot中自定义Starter
java·spring boot·后端
苍煜2 小时前
慢SQL优化实战教学
java·数据库·sql
AI进化营-智能译站2 小时前
ROS2 C++开发系列16-智能指针管理传感器句柄|告别ROS2节点内存泄漏与野指针
java·c++·算法·ai
TeDi TIVE3 小时前
springboot和springframework版本依赖关系
java·spring boot·后端
二哈赛车手3 小时前
新人笔记---ES和kibana启动问题以及一些常用的linux的错误排查方法,以及ES,数据库泄密解决方案[超详细]
java·linux·数据库·spring boot·笔记·elasticsearch
嵌入式×边缘AI:打怪升级日志3 小时前
嵌入式Linux开发核心自测题(全系列精华浓缩)
java·linux·运维
FQNmxDG4S3 小时前
JVM内存模型详解:堆、栈、方法区与垃圾回收
java·jvm·算法
jason.zeng@15022074 小时前
Androidr入门环境搭建
java·kotlin