package com.xxx.tax.util;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.bouncycastle.asn1.gm.GMNamedCurves;
import org.bouncycastle.asn1.x9.X9ECParameters;
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 org.bouncycastle.math.ec.ECPoint;
import org.bouncycastle.util.encoders.Hex;
import javax.crypto.Cipher;
import java.math.BigInteger;
import java.security.InvalidAlgorithmParameterException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.ECGenParameterSpec;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
/**
* SM2加密
*
* @author hcf
* @date 2021/9/1 14:31
*/
@Slf4j
public class Sm2Utils {
/**
* SM2 生成公私钥
*
* @return 公私钥
*/
public static Map<String, String> generateKeyPair() {
Map<String, String> resultMap = new HashMap<>(2);
try {
BouncyCastleProvider provider = new BouncyCastleProvider();
// 获取椭圆曲线相关生成参数规格
ECGenParameterSpec genParameterSpec = new ECGenParameterSpec("sm2p256v1");
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("EC", provider);
// 使用SM2的算法区域初始化密钥生成器
keyPairGenerator.initialize(genParameterSpec, new SecureRandom());
// 生成密钥对
KeyPair keyPair = keyPairGenerator.generateKeyPair();
BCECPrivateKey exPrivateKey = (BCECPrivateKey) keyPair.getPrivate();
BCECPublicKey ecPublicKey = (BCECPublicKey) keyPair.getPublic();
// 解密密钥
BigInteger privateKey = exPrivateKey.getD();
// 加密密钥
ECPoint publicKey = ecPublicKey.getQ();
resultMap.put("privateKey", privateKey.toString(16));
resultMap.put("publicKey", new String(Hex.encode(publicKey.getEncoded(true))));
} catch (NoSuchAlgorithmException | InvalidAlgorithmParameterException e) {
log.info("NoSuchAlgorithmException | InvalidAlgorithmParameterException {}", e.getMessage(), e);
}
return resultMap;
}
public static String printHexString(byte[] b) {
StringBuilder builder = new StringBuilder();
for (int i = 0; i < b.length; i++) {
String hex = Integer.toHexString(b[i] & 0xFF);
if (hex.length() == 1) {
builder.append('0'+hex);
hex = '0' + hex;
}else {
builder.append(hex);
}
//System.out.print(hex.toLowerCase());
}
System.out.println(builder.toString());
return builder.toString();
}
/**
* sm2 加密
*
* @param publicKey 公钥
* @param content 内容
* @return 密文
*/
public static String encrypt(String publicKey, String content) {
String contentEncrypt = StringUtils.EMPTY;
try {
BouncyCastleProvider provider = new BouncyCastleProvider();
// 获取SM2相关参数
X9ECParameters parameters = GMNamedCurves.getByName("sm2p256v1");
// 椭圆曲线参数规格
ECParameterSpec ecParameterSpec = new ECParameterSpec(parameters.getCurve(), parameters.getG(), parameters.getN(), parameters.getH());
// 将公钥HEX字符串转换为椭圆曲线对应的点
ECPoint ecPoint = parameters.getCurve().decodePoint(Hex.decode(publicKey));
// 获取椭圆曲线KEY生成器
KeyFactory keyFactory = KeyFactory.getInstance("EC", provider);
// 将椭圆曲线点转为公钥KEY对象
BCECPublicKey bcecPublicKey = (BCECPublicKey) keyFactory.generatePublic(new ECPublicKeySpec(ecPoint, ecParameterSpec));
// 获取SM2加密器
Cipher cipher = Cipher.getInstance("SM2", provider);
// 初始化为加密模式
cipher.init(Cipher.ENCRYPT_MODE, bcecPublicKey);
// 加密并编码为base64格式
contentEncrypt = Base64.getEncoder().encodeToString(cipher.doFinal(content.getBytes()));
} catch (Exception e) {
log.info("SM2Utils.encrypt(java.lang.String, java.lang.String) error {}", e.getMessage(), e);
}
return printHexString(contentEncrypt.getBytes());
//return contentEncrypt;
}
/**
* sm2 加密
*
* @param publicKey 公钥
* @param content 内容
* @return 密文
*/
public static String encrypt(String publicKey, byte[] content) {
return encrypt(publicKey, new String(content));
}
/**
* sm2 加密
*
* @param privateKey 私钥
* @param contentDecrypt 密文
* @return 明文
*/
public static String decrypt(String privateKey, String contentDecrypt) {
String content = StringUtils.EMPTY;
try {
BouncyCastleProvider provider = new BouncyCastleProvider();
// 获取SM2相关参数
X9ECParameters parameters = GMNamedCurves.getByName("sm2p256v1");
// 椭圆曲线参数规格
ECParameterSpec ecParameterSpec = new ECParameterSpec(parameters.getCurve(), parameters.getG(), parameters.getN(), parameters.getH());
// 将私钥HEX字符串转换为X值
BigInteger bigInteger = new BigInteger(privateKey, 16);
// 获取椭圆曲线KEY生成器
KeyFactory keyFactory = KeyFactory.getInstance("EC", provider);
// 将X值转为私钥KEY对象
BCECPrivateKey bcecPrivateKey = (BCECPrivateKey) keyFactory.generatePrivate(new ECPrivateKeySpec(bigInteger, ecParameterSpec));
// 获取SM2加密器
Cipher cipher = Cipher.getInstance("SM2", provider);
// 初始化为加密模式
cipher.init(Cipher.DECRYPT_MODE, bcecPrivateKey);
// 解密
content = new String(cipher.doFinal(Base64.getDecoder().decode(contentDecrypt)));
} catch (Exception e) {
log.info("SM2Utils.encrypt(java.lang.String, java.lang.String) error {}", e.getMessage(), e);
}
return content;
}
/**
* sm2 加密
*
* @param privateKey 私钥
* @param contentDecrypt 密文
* @return 明文
*/
public static String decrypt(String privateKey, byte[] contentDecrypt) {
return decrypt(privateKey, new String(contentDecrypt));
}
public static void main(String[] args) {
String publicKey = "043048E9968B72DDF70983B8E305217D94C1E02A5BD4875B625ACC3B13512641A7AD7DF0A1A39F453675EB4B085D8B9E05433E91DBE716E80A7219C2485F28B01F";
System.out.println(encrypt(publicKey, "8F6190402EC4F423"));
}
}
如有问题,请私信。
xObP8s/gudi/zrPMoaJKU7K5u7e+s7/Os8yhokpBVkHP4LnYv86zzMjn0OjSqtKyv8nS1MGqz7VRUaGjDQoNCtf31d8gUVEgNDA0NTQwMjI5