由于等保和多個系統(tǒng)間的數(shù)據(jù)傳輸加密, 寫了一個共有的前端與后端, 后端與后端,的通用算法SM2簡單加密,? 不需要驗簽, 幾行代碼搞定.?
引包, 測試好幾遍, 這個包適合jdk1.8使用
1、后端代碼示例
引包,
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk18on</artifactId>
<version>1.72</version>
</dependency>
沒有意外就應該直接能用下面代碼了
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;
/**
* 簡單的sm2
*/
public class SimpSM2Util {
/**
* SM2加密算法
* @param publicKey 公鑰
* @param data 明文數(shù)據(jù)
* @return
*/
public static String encrypt(String publicKey, String data) {
// 獲取一條SM2曲線參數(shù)
X9ECParameters sm2ECParameters = GMNamedCurves.getByName("sm2p256v1");
// 構造ECC算法參數(shù),曲線方程、橢圓曲線G點、大整數(shù)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加密時出現(xiàn)異常:"+e.getMessage());
}
return Hex.toHexString(arrayOfBytes);
}
/**
* SM2解密算法
* @param privateKey 私鑰
* @param cipherData 密文數(shù)據(jù)
* @return
*/
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曲線參數(shù)
X9ECParameters sm2ECParameters = GMNamedCurves.getByName("sm2p256v1");
//構造domain參數(shù)
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解密時出現(xiàn)異常:"+e.getMessage());
}
return result;
}
/*@Test
// 生成密鑰
public void createKey() throws Exception{
//String M="encryption standard111111111111111111111111111111";
SimpSM2Util sm2 = new SimpSM2Util();
ECGenParameterSpec sm2Spec = new ECGenParameterSpec("sm2p256v1");
// 獲取一個橢圓曲線類型的密鑰對生成器
KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC", new BouncyCastleProvider());
// 使用SM2參數(shù)初始化生成器
kpg.initialize(sm2Spec);
// 獲取密鑰對
KeyPair keyPair = kpg.generateKeyPair();
PublicKey publicKey = keyPair.getPublic();
BCECPublicKey p=(BCECPublicKey)publicKey;
System.out.println("publicKey:"+Hex.toHexString(p.getQ().getEncoded(false)));
PrivateKey privateKey = keyPair.getPrivate();
BCECPrivateKey s=(BCECPrivateKey)privateKey;
System.out.println("privateKey:"+Hex.toHexString(s.getD().toByteArray()));
}*/
}
? ? publicKey:04aa909915f87880507e3de515220cc8f82b1c5693f56a0475b3b48ff7448c229734cd724e603000dd78569faa9fbc1eeb93a6d836190a0ee734e2d9e74d804f28
? ? privateKey:00a684d832831d5371d2ff9de6a021a33fb396451e74e0ffe0d415c298b36876fe
加密:? SimpSM2Util.encrypt("共有密鑰", "明文");?
解密:? SimpSM2Util.decrypt("私有密鑰", "密文");
后端代碼使用一個工具類, 可參考
import org.bouncycastle.crypto.engines.SM2Engine;
/**
* 簡單單例SM2加解密, 配合前端
*/
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;
}
/**
* SM2初始密鑰(私鑰,公鑰)
* @param privateKey
* @param publicKey
* @return
*/
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;
}
}
/**
* SM2加密
* @param cleartext 明文數(shù)據(jù)
*/
public String encrypt(String cleartext) {
if(!IsInitKey())
return "";
return SimpSM2Util.encrypt(instance.publicKey, cleartext);
}
/**
* SM2解密
* @param cipherData 密文數(shù)據(jù)
*/
public static String decrypt(String cipherData) {
if(!IsInitKey())
return "";
return SimpSM2Util.decrypt(instance.privateKey, cipherData);
}
}
2、前端代碼示例
安裝sm-crypto包:? ?npm install --save?sm-crypto
前端加解密更簡單,? 引包后就能用
let txt='簡單加密不要驗簽' //要加密的字段
const sm2 = require('sm-crypto').sm2
const cipherMode = 1;// 1 - C1C3C2,0 - C1C2C3,默認為1
var publicKey = "04aa909915f87880507e3de515220cc8f82b1c5693f56a0475b3b48ff7448c229734cd724e603000dd78569faa9fbc1eeb93a6d836190a0ee734e2d9e74d804f28";
// 加密結果
let encryptData = sm2.doEncrypt(txt, publicKey, cipherMode);
// 解密
sm2.doDecrypt(txt, privateKey, cipherMode);
適合簡單的傳輸加密
3、避坑指南
在引用?bcprov-jdk18on 包的時候, 有可能存在版本沖突, 或本地安全問題,? 這個是我在返回切換工程遇到的問題?
可以嘗試把?bcprov-jdk18on-1.72.jar 加入mvn的import的sdks里面
還可以試試?mvn idea:module文章來源:http://www.zghlxwxcb.cn/news/detail-592598.html
或者試試? mvn: idea:idea文章來源地址http://www.zghlxwxcb.cn/news/detail-592598.html
到了這里,關于適用于前后端公用的SM2國密加密傳輸, JAVA + VUE的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!