取消使用hutool的工具进行sm2和aes的加解密

This commit is contained in:
=
2023-11-15 12:11:22 +08:00
parent 9c5ad7aa72
commit 3b77ecddb9
4 changed files with 301 additions and 13 deletions
@@ -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,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);*/
}
}