取消使用hutool的工具进行sm2和aes的加解密
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
package org.dromara.neutrinoproxy.core.util;
|
||||
|
||||
import cn.hutool.core.util.RandomUtil;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Base64;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* AES工具
|
||||
*/
|
||||
public class AesUtil {
|
||||
|
||||
public static byte[] generateKey() {
|
||||
byte[] keyBytes = new byte[16];
|
||||
Random random = RandomUtil.getRandom(true);
|
||||
random.nextBytes(keyBytes);
|
||||
return keyBytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* AES解密
|
||||
* @param decryptKey 秘钥,16位
|
||||
* @param encryptBytes 密文
|
||||
* @return 明文
|
||||
* @throws Exception
|
||||
*/
|
||||
public static byte[] decrypt(byte[] decryptKey, byte[] encryptBytes) {
|
||||
try{
|
||||
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
|
||||
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(decryptKey, "AES"));
|
||||
return cipher.doFinal(encryptBytes);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* AES加密
|
||||
* @param encryptKey 秘钥,必须为16个字符组成
|
||||
* @param data 明文
|
||||
* @return 密文
|
||||
* @throws Exception
|
||||
*/
|
||||
public static byte[] encrypt(byte[] encryptKey, byte[] data) {
|
||||
try {
|
||||
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
|
||||
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(encryptKey, "AES"));
|
||||
return cipher.doFinal(data);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+27
-13
@@ -27,10 +27,15 @@ import cn.hutool.crypto.SecureUtil;
|
||||
import cn.hutool.crypto.SmUtil;
|
||||
import cn.hutool.crypto.symmetric.SymmetricAlgorithm;
|
||||
import cn.hutool.crypto.symmetric.SymmetricCrypto;
|
||||
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey;
|
||||
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
|
||||
import org.bouncycastle.util.encoders.Hex;
|
||||
import org.dromara.neutrinoproxy.core.KeyPairRecord;
|
||||
|
||||
import javax.crypto.SecretKey;
|
||||
import java.security.KeyPair;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.PublicKey;
|
||||
|
||||
/**
|
||||
* 国密算法加解密工具
|
||||
@@ -44,14 +49,25 @@ public class EncryptUtil {
|
||||
* @return
|
||||
*/
|
||||
public static KeyPairRecord generateSm2KeyPair() {
|
||||
KeyPair keyPair = SecureUtil.generateKeyPair("SM2");
|
||||
byte[] privateKeyBytes = keyPair.getPrivate().getEncoded();
|
||||
byte[] publicKeyBytes = keyPair.getPublic().getEncoded();
|
||||
|
||||
String privateKey = HexUtil.encodeHexStr(privateKeyBytes);
|
||||
String publicKey = HexUtil.encodeHexStr(publicKeyBytes);
|
||||
String privateKeyHex = null;
|
||||
String publicKeyHex = null;
|
||||
|
||||
return new KeyPairRecord(privateKey, publicKey);
|
||||
KeyPair keyPair = Sm2Util.createECKeyPair();
|
||||
|
||||
PrivateKey privateKey = keyPair.getPrivate();
|
||||
if (privateKey instanceof BCECPrivateKey) {
|
||||
//获取32字节十六进制私钥串
|
||||
privateKeyHex = ((BCECPrivateKey) privateKey).getD().toString(16);
|
||||
}
|
||||
|
||||
PublicKey publicKey = keyPair.getPublic();
|
||||
if (publicKey instanceof BCECPublicKey) {
|
||||
//获取65字节非压缩缩的十六进制公钥串(0x04)
|
||||
publicKeyHex = Hex.toHexString(((BCECPublicKey) publicKey).getQ().getEncoded(false));
|
||||
}
|
||||
|
||||
return new KeyPairRecord(privateKeyHex, publicKeyHex);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -61,7 +77,7 @@ public class EncryptUtil {
|
||||
* @return 加密后的字节数组
|
||||
*/
|
||||
public static byte[] encryptBySm2(String publicKey, byte[] data) {
|
||||
return SmUtil.sm2(null, publicKey).encrypt(data);
|
||||
return Sm2Util.encrypt(publicKey, data);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -71,7 +87,7 @@ public class EncryptUtil {
|
||||
* @return 解密后的字节数组
|
||||
*/
|
||||
public static byte[] decryptBySm2(String privateKey, byte[] data) {
|
||||
return SmUtil.sm2(privateKey, null).decrypt(data);
|
||||
return Sm2Util.decrypt(privateKey, data);
|
||||
}
|
||||
|
||||
public static byte[] generateSm4Key() {
|
||||
@@ -99,7 +115,7 @@ public class EncryptUtil {
|
||||
}
|
||||
|
||||
public static byte[] generateAesKey() {
|
||||
return SecureUtil.generateKey(SymmetricAlgorithm.AES.getValue()).getEncoded();
|
||||
return AesUtil.generateKey();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -109,8 +125,7 @@ public class EncryptUtil {
|
||||
* @return 加密后的数据
|
||||
*/
|
||||
public static byte[] encryptByAes(byte[] key, byte[] data) {
|
||||
SymmetricCrypto aes = new SymmetricCrypto(SymmetricAlgorithm.AES, key);
|
||||
return aes.encrypt(data);
|
||||
return AesUtil.encrypt(key, data);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -120,8 +135,7 @@ public class EncryptUtil {
|
||||
* @return 解密后的数据
|
||||
*/
|
||||
public static byte[] decryptByAes(byte[] key, byte[] encryptedData) {
|
||||
SymmetricCrypto aes = new SymmetricCrypto(SymmetricAlgorithm.AES, key);
|
||||
return aes.decrypt(encryptedData);
|
||||
return AesUtil.decrypt(key, encryptedData);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,216 @@
|
||||
package org.dromara.neutrinoproxy.core.util;
|
||||
|
||||
import org.bouncycastle.asn1.gm.GMNamedCurves;
|
||||
import org.bouncycastle.asn1.x9.X9ECParameters;
|
||||
import org.bouncycastle.crypto.engines.SM2Engine;
|
||||
import org.bouncycastle.crypto.params.ECDomainParameters;
|
||||
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.jcajce.provider.asymmetric.ec.BCECPublicKey;
|
||||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||
import org.bouncycastle.jce.spec.ECParameterSpec;
|
||||
import org.bouncycastle.jce.spec.ECPrivateKeySpec;
|
||||
import org.bouncycastle.jce.spec.ECPublicKeySpec;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.security.KeyPair;
|
||||
import java.security.KeyPairGenerator;
|
||||
import java.security.SecureRandom;
|
||||
import java.security.spec.ECGenParameterSpec;
|
||||
|
||||
/**
|
||||
* @ClassName SM2Utils
|
||||
* @Description SM2算法工具类
|
||||
*/
|
||||
public class Sm2Util {
|
||||
|
||||
/**
|
||||
* @Description 生成秘钥对
|
||||
* @return KeyPair
|
||||
*/
|
||||
public static KeyPair createECKeyPair() {
|
||||
//使用标准名称创建EC参数生成的参数规范
|
||||
final ECGenParameterSpec sm2Spec = new ECGenParameterSpec("sm2p256v1");
|
||||
|
||||
// 获取一个椭圆曲线类型的密钥对生成器
|
||||
final KeyPairGenerator kpg;
|
||||
try {
|
||||
kpg = KeyPairGenerator.getInstance("EC", new BouncyCastleProvider());
|
||||
// 使用SM2算法域参数集初始化密钥生成器(默认使用以最高优先级安装的提供者的 SecureRandom 的实现作为随机源)
|
||||
// kpg.initialize(sm2Spec);
|
||||
|
||||
// 使用SM2的算法域参数集和指定的随机源初始化密钥生成器
|
||||
kpg.initialize(sm2Spec, new SecureRandom());
|
||||
|
||||
// 通过密钥生成器生成密钥对
|
||||
return kpg.generateKeyPair();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @Description 公钥加密
|
||||
* @param publicKeyHex SM2十六进制公钥
|
||||
* @param data 明文数据
|
||||
* @return String
|
||||
*/
|
||||
public static byte[] encrypt(String publicKeyHex, byte[] data) {
|
||||
return encrypt(getECPublicKeyByPublicKeyHex(publicKeyHex), data, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Description 公钥加密
|
||||
* @param publicKey SM2公钥
|
||||
* @param data 明文数据
|
||||
* @param modeType 加密模式
|
||||
* @return String
|
||||
*/
|
||||
public static byte[] encrypt(BCECPublicKey publicKey, byte[] data, int modeType) {
|
||||
//加密模式
|
||||
SM2Engine.Mode mode = SM2Engine.Mode.C1C3C2;
|
||||
if (modeType != 1) {
|
||||
mode = SM2Engine.Mode.C1C2C3;
|
||||
}
|
||||
//通过公钥对象获取公钥的基本域参数。
|
||||
ECParameterSpec ecParameterSpec = publicKey.getParameters();
|
||||
ECDomainParameters ecDomainParameters = new ECDomainParameters(ecParameterSpec.getCurve(),
|
||||
ecParameterSpec.getG(), ecParameterSpec.getN());
|
||||
//通过公钥值和公钥基本参数创建公钥参数对象
|
||||
ECPublicKeyParameters ecPublicKeyParameters = new ECPublicKeyParameters(publicKey.getQ(), ecDomainParameters);
|
||||
//根据加密模式实例化SM2公钥加密引擎
|
||||
SM2Engine sm2Engine = new SM2Engine(mode);
|
||||
//初始化加密引擎
|
||||
sm2Engine.init(true, new ParametersWithRandom(ecPublicKeyParameters, new SecureRandom()));
|
||||
byte[] arrayOfBytes = null;
|
||||
try {
|
||||
//将明文字符串转换为指定编码的字节串
|
||||
//通过加密引擎对字节数串行加密
|
||||
arrayOfBytes = sm2Engine.processBlock(data, 0, data.length);
|
||||
} catch (Exception e) {
|
||||
System.out.println("SM2加密时出现异常:" + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
//将加密后的字节串转换为十六进制字符串
|
||||
return arrayOfBytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @Description 私钥解密
|
||||
* @param privateKeyHex SM2十六进制私钥
|
||||
* @param cipherData 密文数据
|
||||
* @return String
|
||||
*/
|
||||
public static byte[] decrypt(String privateKeyHex, byte[] cipherData) {
|
||||
return decrypt(getBCECPrivateKeyByPrivateKeyHex(privateKeyHex), cipherData, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Description 私钥解密
|
||||
* @param privateKey SM私钥
|
||||
* @param cipherDataByte 密文数据
|
||||
* @param modeType 解密模式
|
||||
* @return
|
||||
*/
|
||||
public static byte[] decrypt(BCECPrivateKey privateKey, byte[] cipherDataByte, int modeType) {
|
||||
//解密模式
|
||||
SM2Engine.Mode mode = SM2Engine.Mode.C1C3C2;
|
||||
if (modeType != 1)
|
||||
mode = SM2Engine.Mode.C1C2C3;
|
||||
//通过私钥对象获取私钥的基本域参数。
|
||||
ECParameterSpec ecParameterSpec = privateKey.getParameters();
|
||||
ECDomainParameters ecDomainParameters = new ECDomainParameters(ecParameterSpec.getCurve(),
|
||||
ecParameterSpec.getG(), ecParameterSpec.getN());
|
||||
//通过私钥值和私钥钥基本参数创建私钥参数对象
|
||||
ECPrivateKeyParameters ecPrivateKeyParameters = new ECPrivateKeyParameters(privateKey.getD(),
|
||||
ecDomainParameters);
|
||||
//通过解密模式创建解密引擎并初始化
|
||||
SM2Engine sm2Engine = new SM2Engine(mode);
|
||||
sm2Engine.init(false, ecPrivateKeyParameters);
|
||||
try {
|
||||
//通过解密引擎对密文字节串进行解密
|
||||
return sm2Engine.processBlock(cipherDataByte, 0, cipherDataByte.length);
|
||||
} catch (Exception e) {
|
||||
System.out.println("SM2解密时出现异常" + e.getMessage());
|
||||
}
|
||||
return new byte[0];
|
||||
}
|
||||
//椭圆曲线ECParameters ASN.1 结构
|
||||
private static X9ECParameters x9ECParameters = GMNamedCurves.getByName("sm2p256v1");
|
||||
//椭圆曲线公钥或私钥的基本域参数。
|
||||
private static ECParameterSpec ecDomainParameters = new ECParameterSpec(x9ECParameters.getCurve(), x9ECParameters.getG(), x9ECParameters.getN());
|
||||
|
||||
/**
|
||||
* @Description 公钥字符串转换为 BCECPublicKey 公钥对象
|
||||
* @param pubKeyHex 64字节十六进制公钥字符串(如果公钥字符串为65字节首个字节为0x04:表示该公钥为非压缩格式,操作时需要删除)
|
||||
* @return BCECPublicKey SM2公钥对象
|
||||
*/
|
||||
public static BCECPublicKey getECPublicKeyByPublicKeyHex(String pubKeyHex) {
|
||||
//截取64字节有效的SM2公钥(如果公钥首个字节为0x04)
|
||||
if (pubKeyHex.length() > 128) {
|
||||
pubKeyHex = pubKeyHex.substring(pubKeyHex.length() - 128);
|
||||
}
|
||||
//将公钥拆分为x,y分量(各32字节)
|
||||
String stringX = pubKeyHex.substring(0, 64);
|
||||
String stringY = pubKeyHex.substring(stringX.length());
|
||||
//将公钥x、y分量转换为BigInteger类型
|
||||
BigInteger x = new BigInteger(stringX, 16);
|
||||
BigInteger y = new BigInteger(stringY, 16);
|
||||
//通过公钥x、y分量创建椭圆曲线公钥规范
|
||||
ECPublicKeySpec ecPublicKeySpec = new ECPublicKeySpec(x9ECParameters.getCurve().createPoint(x, y), ecDomainParameters);
|
||||
//通过椭圆曲线公钥规范,创建出椭圆曲线公钥对象(可用于SM2加密及验签)
|
||||
return new BCECPublicKey("EC", ecPublicKeySpec, BouncyCastleProvider.CONFIGURATION);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Description 私钥字符串转换为 BCECPrivateKey 私钥对象
|
||||
* @param privateKeyHex 32字节十六进制私钥字符串
|
||||
* @return BCECPrivateKey SM2私钥对象
|
||||
*/
|
||||
public static BCECPrivateKey getBCECPrivateKeyByPrivateKeyHex(String privateKeyHex) {
|
||||
//将十六进制私钥字符串转换为BigInteger对象
|
||||
BigInteger d = new BigInteger(privateKeyHex, 16);
|
||||
//通过私钥和私钥域参数集创建椭圆曲线私钥规范
|
||||
ECPrivateKeySpec ecPrivateKeySpec = new ECPrivateKeySpec(d, ecDomainParameters);
|
||||
//通过椭圆曲线私钥规范,创建出椭圆曲线私钥对象(可用于SM2解密和签名)
|
||||
return new BCECPrivateKey("EC", ecPrivateKeySpec, BouncyCastleProvider.CONFIGURATION);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
/*String publicKeyHex = null;
|
||||
String privateKeyHex = null;*/
|
||||
/*KeyPair keyPair = createECKeyPair();
|
||||
PublicKey publicKey = keyPair.getPublic();
|
||||
if (publicKey instanceof BCECPublicKey) {
|
||||
//获取65字节非压缩缩的十六进制公钥串(0x04)
|
||||
publicKeyHex = Hex.toHexString(((BCECPublicKey) publicKey).getQ().getEncoded(false));
|
||||
System.out.println("---->SM2公钥:" + publicKeyHex);
|
||||
}
|
||||
PrivateKey privateKey = keyPair.getPrivate();
|
||||
if (privateKey instanceof BCECPrivateKey) {
|
||||
//获取32字节十六进制私钥串
|
||||
privateKeyHex = ((BCECPrivateKey) privateKey).getD().toString(16);
|
||||
System.out.println("---->SM2私钥:" + privateKeyHex);
|
||||
}*/
|
||||
|
||||
/**
|
||||
* 公钥加密
|
||||
*/
|
||||
// String data = "az";
|
||||
|
||||
//将十六进制公钥串转换为 BCECPublicKey 公钥对象
|
||||
/*String encryptData = encrypt(publicKeyHex, data);
|
||||
System.out.println("---->加密结果:" + encryptData);*/
|
||||
|
||||
/**
|
||||
* 私钥解密
|
||||
*/
|
||||
//将十六进制私钥串转换为 BCECPrivateKey 私钥对象
|
||||
/*data = decrypt("xx", "xx");
|
||||
System.out.println("---->解密结果:" + data);*/
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user