接口安全设计原则的一个点就是数据不能明文传输,除了https这个必须的请求外,接口数据加密也是一个重要的方式,下面介绍一下SM2国密算法加解密的使用方式。
这里我就针对目前前后端分离架构的方式来简单介绍一下如何正确使用
SM2
算法对数据进行加解密,介绍分为后端加解密和前端加解密。
1.后端加解密
1.1 导入POM依赖
<!-- hutool --><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.8.5</version></dependency><!-- 加解密依赖包 --><dependency><groupId>org.bouncycastle</groupId><artifactId>bcprov-jdk15to18</artifactId><version>1.71</version></dependency>
1.2 生成公钥、私钥密钥对
/**
* 生成公钥、私钥,这个保存好,尤其是私钥,切记不可泄漏
*/publicstaticvoidgenerateCommonKey(){SM2 sm2 =SmUtil.sm2();// 私钥:这个保存好,切记不要泄漏,真的泄露了就重新生成一下byte[] privateKey =BCUtil.encodeECPrivateKey(sm2.getPrivateKey());// 公钥:这个是前后端加密用的,不压缩选择带04的,不带04到时候前端会报错byte[] publicKey =((BCECPublicKey) sm2.getPublicKey()).getQ().getEncoded(false);Console.log("公钥:\n{}",HexUtil.encodeHexStr(publicKey));Console.log("私钥:\n{}",HexUtil.encodeHexStr(privateKey));}
1.3 加解密
/**
* sm2明文加密
* PRIVATE_KEY:生成的私钥
* PUBLIC_KEY:生成的公钥
* @param data 加密前的明文
* @return 加密后的密文
*/publicstaticStringencryptData(String data){SM2 sm2 =SmUtil.sm2(ECKeyUtil.toSm2PrivateParams(PRIVATE_KEY),ECKeyUtil.toSm2PublicParams(PUBLIC_KEY));String encryptBcd = sm2.encryptBcd(data,KeyType.PublicKey);// 这里的处理前端也可以处理,这个就看怎么约定了,其实都无伤大雅if(StrUtil.isNotBlank(encryptBcd)){// 生成的加密密文会带04,因为前端sm-crypto默认的是1-C1C3C2模式,这里需去除04才能正常解密if(encryptBcd.startsWith("04")){
encryptBcd = encryptBcd.substring(2);}// 前端解密时只能解纯小写形式的16进制数据,这里需要将所有大写字母转化为小写
encryptBcd = encryptBcd.toLowerCase();}return encryptBcd;}/**
* sm2密文解密
* PRIVATE_KEY:生成的私钥
* PUBLIC_KEY:生成的公钥
* @param encryptData 加密密文
* @return 解密后的明文字符串
*/publicstaticStringdecryptData(String encryptData)throwsException{if(StrUtil.isBlank(encryptData)){thrownewRuntimeException("解密串为空,解密失败");}SM2 sm2 =SmUtil.sm2(ECKeyUtil.toSm2PrivateParams(PRIVATE_KEY),ECKeyUtil.toSm2PublicParams(PUBLIC_KEY));// BC库解密时密文开头必须带04,如果没带04则需补齐if(!encryptData.startsWith("04")){
encryptData ="04".concat(encryptData);}byte[] decryptFromBcd = sm2.decryptFromBcd(encryptData,KeyType.PrivateKey);if(decryptFromBcd !=null&& decryptFromBcd.length >0){returnStrUtil.utf8Str(decryptFromBcd);}else{thrownewException("密文解密失败");}}
2.前端加解密
2.1 安装NPM包依赖
npminstall --save sm-crypto
2.2 新建公共sm2.js
const sm2 =require('sm-crypto').sm2;// 加密策略,1 - C1C3C2,0 - C1C2C3,默认为1const encryptMode =1;const publicUiKey ='后端生成的公钥';const privateKey ='后端生成的私钥';/**
* 加密数据
* @param {Object} data 明文数据
*/exportfunctionencryptData(data){if(data &&(typeof data ==='string')&&(data.constructor === String)){return'04'.concat(sm2.doEncrypt(data, publicUiKey, encryptMode));}return data;}/**
* 加密对象数据
* @param {Object} data 对象明文
*/exportfunctionencryptObjectData(data){if(data){return'04'.concat(sm2.doEncrypt(JSON.stringify(data), publicUiKey, encryptMode));}return data;}/**
* 解密数据
* @param {Object} dataHex 加密的密文数据
*/exportfunctiondecryptData(encryptData){if(encryptData &&(typeof encryptData ==='string')&&(encryptData.constructor === String)){const decryptData = sm2.doDecrypt(encryptData, privateKey, encryptMode);return decryptData;}}
2.3 使用
import{ encryptData, decryptData}from"../../../request/sm2.js";encryptData('明文');decryptData('密文');
3.参考文档
本文转载自: https://blog.csdn.net/active_pig/article/details/126921695
版权归原作者 皮皮的小猪仔 所有, 如有侵权,请联系我们删除。
版权归原作者 皮皮的小猪仔 所有, 如有侵权,请联系我们删除。