加密-国密-非对称-SM2
国家密码管理局于2010年12月17日发布了SM2算法,并要求现有的基于RSA算法的电子认证系统、密钥管理系统、应用系统进升级改造,使用支持国密SM2算法的证书。
我国现阶段使用的国密SM2算法是在椭圆曲线密码理论基础进行改进而来,其加密强度比RSA算法(2048位)更高。
前段vue + 后端springboot;
思路: 后端使用hutools工具生成公私钥(公130,私64);并且可以进行加解密。
前段使用的公钥加密,生成密文后,但是在后端解密的时候,解不出来。原因需要在密文前面加04
1.前段加密:
后端会生成密钥对(公钥(publicKey),私钥(privateKey)) vue使用sm2加密 1.安装下载依赖:npm install --save sm-crypto 下载报错的话可以用淘宝镜像下载:npm install chromedriver --chromedriver_cdnurl=http://cdn.npm.taobao.org/dist/chromedriver 2.sm2在vue中使用: const sm2 = require('sm-crypto').sm2 const cipherMode = 1 // 1 - C1C3C2,0 - C1C2C3,默认为1 let encryptData = sm2.doEncrypt('需要加密的字符', publicKey, cipherMode) // 加密结果 let decryptData = sm2.doDecrypt(encryptData, privateKey, cipherMode) // 解密结果 //给后端(java)传值时需要在加密的密文前面加04 (`04${encryptData}`),这样后端才能解密正确不报错;
1.1 vue 引入js
vue 中
<script>
import { sm2Encrypt, sm2Decrypt } from '@/utils/sm2Encrypt'
sm2Encrypt.js

const publicKey = '130' const privateKey = '64' const sm2 = require('sm-crypto').sm2 const cipherMode = 1 // 1 - C1C3C2,0 - C1C2C3,默认为1 // 加密 export function sm2Encrypt(txt) { let encryptData = sm2.doEncrypt(txt, publicKey, cipherMode) // 加密结果 return encryptData } // 解密 export function sm2Decrypt(txt) { let decryptData = sm2.doDecrypt(txt, privateKey, cipherMode) // 解密结果 return decryptData; }
2.后端解密
2.1pom中引入依赖
<!-- hutool工具类 --> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.7.4</version> </dependency> <!-- 第三方加密功能依赖sm2 --> <dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcprov-jdk15to18</artifactId> <version>1.69</version> </dependency>
<!--
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.56</version>
</dependency>
-->
相关代码:
package com.sinosoft; import cn.hutool.core.util.HexUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.crypto.BCUtil; import cn.hutool.crypto.SmUtil; import cn.hutool.crypto.asymmetric.KeyType; import cn.hutool.crypto.asymmetric.SM2; import lombok.extern.slf4j.Slf4j; import org.bouncycastle.crypto.engines.SM2Engine; import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import java.nio.charset.Charset; //import org.junit.runner.RunWith; /** * TODO * * @author zhaoJs * @version 1.0 * @date 2022/9/2 15:07 */ @SpringBootTest (classes = Sm2Test.class) @RunWith(SpringRunner.class) @Slf4j public class Sm2Test { String privateKey = "00ac90ec091563b319bdf2e449df659940f24e14beaf09935a92b260fa68c6c8ac"; String publicKey = "0462a7f3ed9cc136465353dffcf0e253723e3b0c1525cf47860901c0c4ba57c8d984bfc6cb0d1d9764498b41e58fd0040a9920d904ad442495e154d2fe68fd2720"; String content = "测试"; //公私钥生成 @Test public void createSM2Key(){ SM2 sm2 = SmUtil.sm2(); // sm2的加解密时有两种方式即 C1C2C3、 C1C3C2, sm2.setMode(SM2Engine.Mode.C1C3C2); // 生成私钥 String privateKey = HexUtil.encodeHexStr(BCUtil.encodeECPrivateKey(sm2.getPrivateKey())); // 生成公钥 String publicKey = HexUtil.encodeHexStr(((BCECPublicKey) sm2.getPublicKey()).getQ().getEncoded(false)); log.info("privateKey:" + privateKey); log.info("publicKey:" + publicKey); } //公钥加密 @Test public void encrypt(){ SM2 sm2 = SmUtil.sm2(null, publicKey); sm2.setMode(SM2Engine.Mode.C1C3C2); // 返回值的字符串,需要注意此处加密后密文为16进制,否则前端解密前需要先转换格式 String encryptStr = sm2.encryptHex(new String(content), Charset.forName("utf-8"), KeyType.PublicKey); log.info("encryptStr:" + encryptStr); } //私钥解密 @Test public void decrypt(){
// 如果是前段vue传来的 密文,需要在密文前加04 String encryptStr = "04f0d63500e8f56243462b17c9489c7ea7bbbb10271f45066cc150e2da934fca72abe396b05639fac1192630c27bd7d3ff553c0f43260e8cdb84c5c6594701f75ce96a49ba0d16368acdc3ef16c211bc638cc47caf05214e8e302c8ddb3798534044d1d6204277"; // 解密 SM2 sm2 = SmUtil.sm2(privateKey, publicKey); sm2.setMode(SM2Engine.Mode.C1C3C2); //String newBody1 = StrUtil.utf8Str(sm2.decryptFromBcd(d, KeyType.PrivateKey)); String decryptStr = sm2.decryptStr(encryptStr, KeyType.PrivateKey, Charset.forName("utf-8")); log.info("decryptStr:" + decryptStr); } }
加密是为了防止信息被泄露,而签名是为了防止信息被篡改。
参考:
SM2 java+hutool方法示例(重点参考)
一文告诉你,国密SM2算法有多优秀
国密SM2的前端加密,后端解密(Java版本)及SM3 摘要加密
国密SM2前端VUE,后端Hutool工具的搭配
前端Vue使用SM2加密、解密方法
vue/java使用国密SM2加密
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 全网最简单!3分钟用满血DeepSeek R1开发一款AI智能客服,零代码轻松接入微信、公众号、小程
· .NET 10 首个预览版发布,跨平台开发与性能全面提升