由于等保和多个系统间的数据传输加密, 写了一个共有的前端与后端, 后端与后端,的通用算法SM2简单加密, 不需要验签, 几行代码搞定.
引包, 测试好几遍, 这个包适合jdk1.8使用
引包,
org.bouncycastle bcprov-jdk18on 1.72
没有意外就应该直接能用下面代码了
import org.bouncycastle.asn1.gm.GMNamedCurves;import org.bouncycastle.asn1.x9.X9ECParameters;import org.bouncycastle.crypto.engines.SM2Engine;import org.bouncycastle.crypto.params.*;import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey;import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;import org.bouncycastle.jce.provider.BouncyCastleProvider;import org.bouncycastle.math.ec.ECPoint;import org.bouncycastle.util.encoders.Hex;import org.junit.Test;import java.math.BigInteger;import java.security.*;import java.security.spec.ECGenParameterSpec;public class SimpSM2Util { public static String encrypt(String publicKey, String data) { // 获取一条SM2曲线参数 X9ECParameters sm2ECParameters = GMNamedCurves.getByName("sm2p256v1"); // 构造ECC算法参数,曲线方程、椭圆曲线G点、大整数N ECDomainParameters domainParameters = new ECDomainParameters(sm2ECParameters.getCurve(), sm2ECParameters.getG(), sm2ECParameters.getN()); //提取公钥点 ECPoint pukPoint = sm2ECParameters.getCurve().decodePoint(Hex.decode(publicKey)); // 公钥前面的02或者03表示是压缩公钥,04表示未压缩公钥, 04的时候,可以去掉前面的04 ECPublicKeyParameters publicKeyParameters = new ECPublicKeyParameters(pukPoint, domainParameters); SM2Engine sm2Engine = new SM2Engine(SM2Engine.Mode.C1C3C2); // 设置sm2为加密模式 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) { System.out.println("SM2加密时出现异常:"+e.getMessage()); } return Hex.toHexString(arrayOfBytes); } public static String decrypt(String privateKey, String cipherData) { // 使用BC库加解密时密文以04开头,传入的密文前面没有04则补上 if (!cipherData.startsWith("04")){ cipherData = "04" + cipherData; } byte[] cipherDataByte = Hex.decode(cipherData); BigInteger privateKeyD = new BigInteger(privateKey, 16); //获取一条SM2曲线参数 X9ECParameters sm2ECParameters = GMNamedCurves.getByName("sm2p256v1"); //构造domain参数 ECDomainParameters domainParameters = new ECDomainParameters(sm2ECParameters.getCurve(), sm2ECParameters.getG(), sm2ECParameters.getN()); ECPrivateKeyParameters privateKeyParameters = new ECPrivateKeyParameters(privateKeyD, domainParameters); SM2Engine sm2Engine = new SM2Engine(SM2Engine.Mode.C1C3C2); // 设置sm2为解密模式 sm2Engine.init(false, privateKeyParameters); String result = ""; try { byte[] arrayOfBytes = sm2Engine.processBlock(cipherDataByte, 0, cipherDataByte.length); return new String(arrayOfBytes); } catch (Exception e) { System.out.println("SM2解密时出现异常:"+e.getMessage()); } return result; } }
publicKey:04aa909915f87880507e3de515220cc8f82b1c5693f56a0475b3b48ff7448c229734cd724e603000dd78569faa9fbc1eeb93a6d836190a0ee734e2d9e74d804f28
privateKey:00a684d832831d5371d2ff9de6a021a33fb396451e74e0ffe0d415c298b36876fe
加密: SimpSM2Util.encrypt("共有密钥", "明文");
解密: SimpSM2Util.decrypt("私有密钥", "密文");
后端代码使用一个工具类, 可参考
import org.bouncycastle.crypto.engines.SM2Engine;public class LoSM2 { private static String ECNameModel = "sm2p256v1"; private static SM2Engine.Mode CipherMode = SM2Engine.Mode.C1C3C2; private final String privateKey; private final String publicKey; private LoSM2(String privateKey, String publicKey){ this.privateKey = privateKey; this.publicKey = publicKey; } private volatile static LoSM2 instance = null; public static LoSM2 getInstance(){ if(instance == null){ throw new RuntimeException("请InitKey初始化密钥!!!"); } return instance; } public static LoSM2 InitKey(String privateKey, String publicKey) { if(instance == null){ synchronized(LoSM2.class){ if(instance == null){ instance = new LoSM2(privateKey, publicKey); } } } return instance; } private static class SM2SimpSelfLoader { private static final LoSM2 instance = InitKey("", ""); } private static boolean IsInitKey(){ if(instance == null) { throw new RuntimeException("请InitKey初始化密钥!!!"); }else { return true; } } public String encrypt(String cleartext) { if(!IsInitKey()) return ""; return SimpSM2Util.encrypt(instance.publicKey, cleartext); } public static String decrypt(String cipherData) { if(!IsInitKey()) return ""; return SimpSM2Util.decrypt(instance.privateKey, cipherData); }}
安装sm-crypto包: npm install --save sm-crypto
前端加解密更简单, 引包后就能用
let txt='简单加密不要验签' //要加密的字段const sm2 = require('sm-crypto').sm2const cipherMode = 1;// 1 - C1C3C2,0 - C1C2C3,默认为1var publicKey = "04aa909915f87880507e3de515220cc8f82b1c5693f56a0475b3b48ff7448c229734cd724e603000dd78569faa9fbc1eeb93a6d836190a0ee734e2d9e74d804f28";// 加密结果 let encryptData = sm2.doEncrypt(txt, publicKey, cipherMode);// 解密sm2.doDecrypt(txt, privateKey, cipherMode);
适合简单的传输加密
在引用 bcprov-jdk18on 包的时候, 有可能存在版本冲突, 或本地安全问题, 这个是我在返回切换工程遇到的问题
可以尝试把 bcprov-jdk18on-1.72.jar 加入mvn的import的sdks里面
还可以试试 mvn idea:module
或者试试 mvn: idea:idea
来源地址:https://blog.csdn.net/coolclouds/article/details/130627364