1、实现前端加密,后端解密,前端需要引入js文件
<script src="/business/libs/crypto-js.js"></script>// js调用方式var encryptData = sm2Encrypt('明文', '公钥', 0);
2、后端SM2生成公私钥及解密
package wst.st.site.tools;import java.math.BigInteger;import java.nio.charset.StandardCharsets;import java.security.SecureRandom;import org.apache.commons.codec.binary.Base64;import org.bouncycastle.asn1.gm.GMNamedCurves;import org.bouncycastle.asn1.x9.X9ECParameters;import org.bouncycastle.crypto.AsymmetricCipherKeyPair;import org.bouncycastle.crypto.engines.SM2Engine;import org.bouncycastle.crypto.generators.ECKeyPairGenerator;import org.bouncycastle.crypto.params.ECDomainParameters;import org.bouncycastle.crypto.params.ECKeyGenerationParameters;import org.bouncycastle.crypto.params.ECPrivateKeyParameters;import org.bouncycastle.crypto.params.ECPublicKeyParameters;import org.bouncycastle.crypto.params.ParametersWithRandom;import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey;import org.bouncycastle.jce.provider.BouncyCastleProvider;import org.bouncycastle.jce.spec.ECParameterSpec;import org.bouncycastle.jce.spec.ECPrivateKeySpec;import org.bouncycastle.math.ec.ECPoint;import org.bouncycastle.util.encoders.Hex;import wst.st.site.constant.SiteWebConstant;/*** SM2工具类** @author wst 2023年8月21日 上午10:32:33**/public class SM2Util {public static void main(String[] args) throws Exception {}/*** 生成密钥** @author wst 2023年8月21日 上午10:37:37*/public static void getPKs() {try {X9ECParameters sm2ECParameters = GMNamedCurves.getByName("sm2p256v1");ECDomainParameters domainParameters = new ECDomainParameters(sm2ECParameters.getCurve(),sm2ECParameters.getG(), sm2ECParameters.getN());ECKeyPairGenerator keyPairGenerator = new ECKeyPairGenerator();keyPairGenerator.init(new ECKeyGenerationParameters(domainParameters, SecureRandom.getInstance("SHA1PRNG")));AsymmetricCipherKeyPair asymmetricCipherKeyPair = keyPairGenerator.generateKeyPair();// 私钥,16进制格式,自己保存BigInteger privatekey = ((ECPrivateKeyParameters) asymmetricCipherKeyPair.getPrivate()).getD();String privateKeyHex = privatekey.toString(16);System.out.println("private Key :" + privateKeyHex);// 公钥,16进制格式,发给前端ECPoint ecPoint = ((ECPublicKeyParameters) asymmetricCipherKeyPair.getPublic()).getQ();String publicKeyHex = Hex.toHexString(ecPoint.getEncoded(false));System.out.println("public Key :" + publicKeyHex);} catch (Exception e) {e.printStackTrace();}}/*** 解密,前端登录信息解码及解码** @author wst 2024年9月12日 下午1:41:47* @param cipherData* @return*/public static String decrypt(String cipherData) {// 得到明文String data = null;try {byte[] cipherDataByte = Hex.decode(cipherData);// sm2私钥BigInteger privateKeyD = new BigInteger(SiteWebConstant.Common.Config.Sm2_Private_Key, 16);X9ECParameters sm2ECParameters1 = GMNamedCurves.getByName("sm2p256v1");ECDomainParameters domainParameters1 = new ECDomainParameters(sm2ECParameters1.getCurve(),sm2ECParameters1.getG(), sm2ECParameters1.getN());ECPrivateKeyParameters privateKeyParameters = new ECPrivateKeyParameters(privateKeyD, domainParameters1);// 用私钥解密SM2Engine sm2Engine = new SM2Engine();sm2Engine.init(false, privateKeyParameters);// 前端传入的密文解密后的processBlock得到Base64格式,记得解码// 如果只用下面给出的加密方法加密则不需要这个解码流程byte[] arrayOfBytes = Base64.decodeBase64(sm2Engine.processBlock(cipherDataByte, 0, cipherDataByte.length));data = new String(arrayOfBytes);} catch (Exception e) {e.printStackTrace();}return data;}/*** 解密* @author wst 2024年9月12日 下午2:44:39* @param cipherData* @return*/public static String sm2decrypt(String cipherData) {String result = null;try {// 加密算法String algorithm = "EC";// 私钥Hex,还原私钥BigInteger privateKeyD = new BigInteger(SiteWebConstant.Common.Config.Sm2_Private_Key, 16);// 使用标准名称创建EC参数生成的参数规范X9ECParameters sm2ECParameters = GMNamedCurves.getByName("sm2p256v1");// 获取私钥的基本域参数ECParameterSpec ecParameterSpec = new ECParameterSpec(sm2ECParameters.getCurve(), sm2ECParameters.getG(),sm2ECParameters.getN());ECPrivateKeySpec ecPrivateKeySpec = new ECPrivateKeySpec(privateKeyD, ecParameterSpec);// 获取私钥对象BCECPrivateKey bcecPrivateKey = new BCECPrivateKey(algorithm, ecPrivateKeySpec,BouncyCastleProvider.CONFIGURATION);byte[] cipherDataByte = Hex.decode(cipherData);ECDomainParameters ecDomainParameters = new ECDomainParameters(ecParameterSpec.getCurve(),ecParameterSpec.getG(), ecParameterSpec.getN());// 通过私钥值和私钥基本参数创建私钥参数对象ECPrivateKeyParameters ecPrivateKeyParameters = new ECPrivateKeyParameters(bcecPrivateKey.getD(),ecDomainParameters);// 通过解密模式创建解密引擎并初始化SM2Engine sm2Engine = new SM2Engine();sm2Engine.init(false, ecPrivateKeyParameters);try {byte[] arrayOfBytes = sm2Engine.processBlock(cipherDataByte, 0, cipherDataByte.length);return new String(arrayOfBytes, StandardCharsets.UTF_8);} catch (Exception e) {}} catch (Exception e) {}return result;}/*** 加密* @author wst 2024年9月12日 下午2:42:21* @param data* @return*/public static String encrypt(String data){// 获取一条SM2曲线参数X9ECParameters sm2ECParameters = GMNamedCurves.getByName("sm2p256v1");// 构造ECC算法参数,曲线方程、椭圆曲线G点、大整数NECDomainParameters domainParameters = new ECDomainParameters(sm2ECParameters.getCurve(), sm2ECParameters.getG(), sm2ECParameters.getN());//提取公钥点ECPoint pukPoint = sm2ECParameters.getCurve().decodePoint(Hex.decode(SiteWebConstant.Common.Config.Sm2_Public_Key));// 公钥前面的02或者03表示是压缩公钥,04表示未压缩公钥, 04的时候,可以去掉前面的04ECPublicKeyParameters publicKeyParameters = new ECPublicKeyParameters(pukPoint, domainParameters);SM2Engine sm2Engine = new SM2Engine();sm2Engine.init(true, new ParametersWithRandom(publicKeyParameters, new SecureRandom()));byte[] arrayOfBytes = null;try {byte[] in = data.getBytes();arrayOfBytes = sm2Engine.processBlock(in, 0, in.length);} catch (Exception e) {e.printStackTrace();}return Hex.toHexString(arrayOfBytes);}}