news 2026/7/28 23:18:39

SpringBoot+Vue实现SM4加密传输

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
SpringBoot+Vue实现SM4加密传输

最近项目中因为密保要求,需要对敏感数据加密传输,目前就用SpringBoot+Vue实现SM4加密传输,目前只是一个基础过渡方案,仅供参考使用。

一、前置准备

1. 后端SpringBoot:引入BouncyCastle依赖

Java这边实现SM4,最常用的就是BouncyCastle这个加密库,直接在pom.xml里加依赖就行,我用的是1.70版本,比较稳定,没什么兼容性问题:

xml

<dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcprov-jdk15on</artifactId> <version>1.70</version> </dependency>

2. 前端Vue:安装sm4js插件

前端这边不用自己造轮子,有现成的sm4js插件可以用,直接npm安装即可,命令很简单:

npm install sm4js

二、后端核心:SM4工具类实现(SpringBoot)

后端的核心就是写一个可复用的SM4工具类,我这里实现了CBC模式(比ECB模式更安全,需要初始化向量IV),同时支持Base64编码(方便网络传输,比Hex更节省空间)。

先给大家贴完整代码,后面再唠关键要点:

java

import lombok.Getter; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.util.encoders.Hex; import javax.crypto.Cipher; import javax.crypto.KeyGenerator; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import java.nio.charset.StandardCharsets; import java.security.SecureRandom; import java.security.Security; import java.util.Base64; import static java.util.Objects.isNull; @Slf4j public class SM4Utils { private static final int DEFAULT_KEY_SIZE = 128; private static final String ALGORITHM = "SM4"; private static final String SM4_ECB_ = "SM4/ECB/"; private static final String SM4_CBC_ = "SM4/CBC/"; private static final Base64.Encoder BASE64_ENCODER = Base64.getEncoder(); private static final Base64.Decoder BASE64_DECODER = Base64.getDecoder(); private static final BouncyCastleProvider PROVIDER = new BouncyCastleProvider(); // 静态代码块:注册BouncyCastle加密提供者 static { if (isNull(Security.getProvider(BouncyCastleProvider.PROVIDER_NAME))) { Security.addProvider(PROVIDER); } } // 填充模式枚举,方便调用,常用PKCS5/PKCS7 @Getter public enum Padding { PKCS5("PKCS5Padding"), PKCS7("PKCS7Padding"), ISO10126("ISO10126Padding"); private final String name; Padding(String name) { this.name = name; } } // 生成Base64格式的SM4密钥(128位,SM4默认密钥长度) public static String genKeyAsBase64() { return genKeyAsBase64(DEFAULT_KEY_SIZE); } public static String genKeyAsBase64(int keySize) { return BASE64_ENCODER.encodeToString(genKey(keySize)); } @SneakyThrows private static byte[] genKey(int keySize) { KeyGenerator kg = KeyGenerator.getInstance(ALGORITHM, BouncyCastleProvider.PROVIDER_NAME); kg.init(keySize, new SecureRandom()); return kg.generateKey().getEncoded(); } // CBC模式:Base64加密(核心业务方法,敏感数据传输用这个) public static String encryptBase64_CBC(String data, String key) { // 固定IV(前后端必须一致!),也可以动态生成后和密文一起传输 String fixedIv = "Wqsdy3M345BV6GRXB"; return BASE64_ENCODER.encodeToString(encrypt_CBC( data.getBytes(StandardCharsets.UTF_8), key.getBytes(StandardCharsets.UTF_8), fixedIv.getBytes(StandardCharsets.UTF_8), Padding.PKCS5 )); } // CBC模式:底层字节数组加密实现 @SneakyThrows private static byte[] encrypt_CBC(byte[] data, byte[] key, byte[] iv, Padding padding) { Cipher cipher = getCipher_CBC(padding); SecretKeySpec secretKeySpec = new SecretKeySpec(key, ALGORITHM); IvParameterSpec ivParameterSpec = new IvParameterSpec(iv); cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec); return cipher.doFinal(data); } // 获取CBC模式的Cipher实例 @SneakyThrows private static Cipher getCipher_CBC(Padding padding) { return Cipher.getInstance(SM4_CBC_ + padding.name, BouncyCastleProvider.PROVIDER_NAME); } // 测试方法 public static void main(String[] args) { // 测试:密钥(前后端一致,可通过genKeyAsBase64()生成) String key = "qwegwfdtwer234"; // 敏感数据 String sensitiveData = "11111"; // 加密结果 String encryptedData = SM4Utils.encryptBase64_CBC(sensitiveData, key); System.out.println("加密后的密文:" + encryptedData); } }

后端关键要点说明

  • 密钥和IV的约定
  • 填充模式:这里用了PKCS5Padding,和前端sm4js的默认填充模式兼容,避免对接时出现填充错误。
  • Base64编码:加密后的字节数组转成Base64字符串,方便通过HTTP接口传输,不会出现乱码问题。

三、前端核心:Vue实现SM4解密

前端的核心是接收后端返回的Base64密文,通过sm4js插件进行解密,还原出原始的敏感数据。我这里封装了一个工具类,方便在项目的各个组件中复用。

1. 可选:全局注册sm4js(方便全局调用)

如果项目中很多地方都需要解密,可以在main.js里全局注册,省去每次引入的麻烦:

javascript

import Sm4js from 'sm4js' Vue.prototype.$sm4 = Sm4js

2. 核心:解密工具类封装

新建一个sm4Utils.js文件,封装解密方法,关键是要和后端的密钥、IV、加密模式、填充模式保持一致,否则解密肯定翻车:

javascript

import Sm4js from 'sm4js'; let sm4Utils = {}; // 解密方法:参数(后端约定的密钥,后端返回的Base64密文) sm4Utils.decryptedData = function(key, data){ // sm4配置项:和后端完全对应! let sm4Config = { key: key, // 密钥:和后端一致(qwegwfdtwer234) iv: 'Wqsdy3M345BV6GRXB', // IV:和后端固定IV一致 mode: 'cbc', // 加密模式:CBC(和后端一致) padding: 'PKCS5Padding' // 填充模式:和后端一致(默认也可以,保险起见显式指定) } // 实例化sm4对象 let sm4 = new Sm4js(sm4Config); // 关键:后端返回的是Base64密文,先通过atob()解码,再进行sm4解密 return sm4.decrypt(atob(data)); } export default sm4Utils;

3. 组件中使用解密工具类

在需要解密的Vue组件中,引入封装好的工具类,直接调用即可,非常方便:

xml

<template> <div> <p>解密后的数据:{{ decryptedResult }}</p> </div> </template> <script> // 引入sm4解密工具类 import sm4Utils from '@/utils/sm4Utils.js'; export default { data() { return { decryptedResult: '', // 解密结果 key: 'qwegwfdtwer234', // 后端约定的密钥 encryptedData: '' // 后端返回的加密密文(接口请求获取) }; }, mounted() { // 模拟接口返回密文,调用解密方法 this.encryptedData = SM4Utils.encryptBase64_CBC("11111","qwegwfdtwer234"); // 后端返回的密文 this.decryptedResult = sm4Utils.decryptedData(this.key, this.encryptedData); } }; </script>

四、总结

该方案其实对数据安全传输提升不明显,后期有较大的提升空间。该方案只能防止「明文传输被窃听」,避免敏感数据被「零成本获取」,是一种「基础的安全防护」,比明文传输略强,但存在较明显的短板。

核心弊端

  1. 密钥安全隐患:前端需持有密钥,无论硬编码还是接口获取,均可能被提取,泄露后加密失效。
  2. 对称加密局限:单密钥加解密,一旦密钥泄露,攻击者可解密所有数据、伪造加密信息。
  3. 前端环境脆弱:浏览器/客户端易被调试、抓包,辅助防护仅增加攻击难度,无法根治泄露风险。
  4. 适用场景有限:仅能抵御基础窃听,无法满高安全等级项目的保密需求。

安全提升方案

  1. 动态生成短期密钥:为每个用户会话生成临时SM4密钥,绑定会话有效期,过期自动失效,降低密钥泄露影响范围。
  2. 非对称加密传密钥:用SM2/RSA加密临时SM4密钥,前端仅存公钥(可公开),后端保管私钥,杜绝密钥传输泄露。
  3. 密钥安全存储与清理:前端密钥不存localStorage,仅驻留内存,会话结束(退出/关页)立即清空,避免残留。
  4. 增加数据校验机制:后端对加密数据添加SM3哈希校验,前端解密后验证,防止数据被篡改伪造。
  5. 前端代码加固:开启代码混淆、禁止调试、密钥分片存储,提升攻击者提取密钥和破解逻辑的难度。
  6. 接口权限与加密结合:对获取密钥/密文的接口做严格权限控制,仅授权用户可访问,多重防护降低风险。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/28 3:22:37

拥有AI员工,才发现误会了领导

人工智能爆火三年&#xff0c;大模型和AI工具好用之后&#xff1a;职场从个人单刷模式&#xff0c;转变成带几个AI助手打团战&#xff0c;可以更高效的干活&#xff0c;但节奏却慢不下来。打工人成领导&#xff0c;不知薪水涨多少&#xff1f;虽说只是几个AI助手&#xff0c;但…

作者头像 李华
网站建设 2026/7/26 1:34:03

GD5F1GM7UEYIGR:兆易创新1Gbit SPI NAND闪存,高效低功耗

品牌&#xff1a;兆易创新(GigaDevice) 型号&#xff1a;GD5F1GM7UEYIGR 容量&#xff1a;1Gbit 产品类型&#xff1a;NAND FLASH 接口类型&#xff1a; 标准SPI接口&#xff0c;支持1、2、4线模式。这意味着它只需要极少&#xff08;通常6-7个&#xff09;的GPIO引脚即可实…

作者头像 李华
网站建设 2026/7/28 19:04:11

九章算Angew. Chem. Int. Ed.解读【水系质子电池】江苏科技大学博士一作最新:几何预构型调控熵受限质子迁移的超快且稳定的水系质子电池

【文章信息】 本文第一作者是江苏科技大学在读博士生刘贺&#xff0c;曾以第一作者或共同作者在Angewandte Chemie、Advanced Functional Materials等期刊发表论文十余篇&#xff0c;欢迎各位科研同行交流。 【研究背景】 水系质子电池&#xff08;Aqueous Proton Batteries, …

作者头像 李华
网站建设 2026/7/28 10:07:45

建模智能体,AI 时代的数据治理新范式

从制度治理到生成式治理的根本转变 1 数据治理是上一代信息化的体系性问题 过去十多年&#xff0c;企业在数据治理上的投入并不算少。沿着数据治理方法论&#xff0c;我们有主数据、元数据、数据标准、数据质量、数据资产目录、数据开发与分析、安全分级分类……几乎每一个治理…

作者头像 李华
网站建设 2026/7/23 21:01:20

苹果手机照片怎么导入电脑?苹果手机传输照片就用这5招

大家的苹果手机中都存储着许多照片吧&#xff0c;它们通常很占内存&#xff0c;无论是为了腾空间&#xff0c;还是安全备份&#xff0c;将照片导入电脑都是一个明智的选择。那&#xff0c;苹果手机照片怎么导入电脑&#xff1f;听起来简单是吧&#xff1f;但实际操作中&#xf…

作者头像 李华
网站建设 2026/7/27 22:55:36

配环境1天,上线3分钟:我把整个团队的本地环境都扔了

“在我电脑上明明是好的”&#xff0c;这句话我曾说过无数次&#xff0c;也听过无数次。一个微小的环境差异&#xff0c;就能让整个团队的联调陷入僵局&#xff0c;浪费掉一下午的时间。在又一次因为环境问题导致上线延期后&#xff0c;我意识到&#xff0c;我们必须彻底抛弃这…

作者头像 李华