
com.siashan.toolkit.crypt.asymmetric.SM2 Maven / Gradle / Ivy
package com.siashan.toolkit.crypt.asymmetric;
import com.siashan.toolkit.crypt.CryptException;
import com.siashan.toolkit.crypt.EncodeType;
import com.siashan.toolkit.crypt.KeyUtil;
import com.siashan.toolkit.crypt.util.BCUtil;
import com.siashan.toolkit.crypt.util.ECKeyUtil;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.InvalidCipherTextException;
import org.bouncycastle.crypto.digests.SM3Digest;
import org.bouncycastle.crypto.engines.SM2Engine;
import org.bouncycastle.crypto.params.ParametersWithID;
import org.bouncycastle.crypto.params.ParametersWithRandom;
import org.bouncycastle.crypto.signers.DSAEncoding;
import org.bouncycastle.crypto.signers.SM2Signer;
import org.bouncycastle.crypto.signers.StandardDSAEncoding;
/**
* 国密SM2算法实现,基于BC库
* SM2算法只支持公钥加密,私钥解密
* 参考:https://blog.csdn.net/pridas/article/details/86118774
*
* @author siashan
* @since 1.0.7
*/
public class SM2 {
/**
* 算法EC
*/
private static final String ALGORITHM_SM2 = "SM2";
/**
* SM2默认曲线
*/
public static final String SM2_CURVE_NAME = "sm2p256v1";
// --------------------------------------------------------------------------------- Encrypt
/**
* 加密,SM2非对称加密的结果由C1,C2,C3三部分组成,其中:
*
*
* C1 生成随机数的计算出的椭圆曲线点
* C2 密文数据
* C3 SM3的摘要值
*
*
* @param data 被加密的bytes
* @param pubKeyParameters 公钥参数
* @return 加密后的bytes
* @throws CryptException 异常
*/
public static byte[] encrypt(byte[] data, CipherParameters pubKeyParameters) throws CryptException {
final SM2Engine engine = getEngine();
try {
engine.init(true, pubKeyParameters);
return engine.processBlock(data, 0, data.length);
} catch (InvalidCipherTextException e) {
throw new CryptException(e);
}
}
/**
* 加密,SM2非对称加密的结果由C1,C2,C3三部分组成,其中:
*
* @param data 被加密的bytes
* @param publicKey 公钥参数
* @return 加密后的bytes
* @throws CryptException 加密异常
*/
public static byte[] encrypt(byte[] data, byte[] publicKey) {
return encrypt(data, ECKeyUtil.toSm2PublicParams(publicKey));
}
/**
* 加密,SM2非对称加密的结果由C1,C2,C3三部分组成,其中:
*
* @param data 被加密的bytes
* @param publicKeyPointX 公钥X
* @param publicKeyPointY 公钥Y
* @return 加密后的bytes
* @throws CryptException 加密异常
*/
public static byte[] encrypt(byte[] data, byte[] publicKeyPointX, byte[] publicKeyPointY) {
return encrypt(data, BCUtil.toSm2Params(publicKeyPointX, publicKeyPointY));
}
/**
* 加密,SM2非对称加密的结果由C1,C2,C3三部分组成,其中:
*
* @param data 被加密的bytes
* @param publicKeyPointXHex 公钥X
* @param publicKeyPointYHex 公钥Y
* @return 加密后的bytes
* @throws CryptException 加密异常
*/
public static byte[] encrypt(byte[] data, String publicKeyPointXHex, String publicKeyPointYHex) {
return encrypt(data, BCUtil.toSm2Params(publicKeyPointXHex, publicKeyPointYHex));
}
/**
* 加密,SM2非对称加密的结果由C1,C2,C3三部分组成,其中:
*
* @param data 被加密的bytes
* @param publicKey 公钥参数
* @return 加密后的bytes
* @throws CryptException 加密异常
*/
public static byte[] encrypt(byte[] data, String publicKey) {
return encrypt(data, KeyUtil.decodeKey(publicKey, EncodeType.HEX));
}
/**
* 加密,SM2非对称加密的结果由C1,C2,C3三部分组成,其中:
*
* @param data 被加密的bytes
* @param publicKey 公钥参数
* @return 加密后的bytes
* @throws CryptException 加密异常
*/
public static byte[] encrypt(byte[] data, String publicKey, EncodeType encodeType) {
return encrypt(data, KeyUtil.decodeKey(publicKey, encodeType));
}
// --------------------------------------------------------------------------------- Decrypt
/**
* 解密
*
* @param data SM2密文,实际包含三部分:ECC公钥、真正的密文、公钥和原文的SM3-HASH值
* @param privateKeyParameters 私钥参数
* @return 加密后的bytes
* @throws CryptException 异常
*/
public static byte[] decrypt(byte[] data, CipherParameters privateKeyParameters) throws CryptException {
final SM2Engine engine = getEngine();
try {
engine.init(false, privateKeyParameters);
return engine.processBlock(data, 0, data.length);
} catch (InvalidCipherTextException e) {
throw new CryptException(e);
}
}
/**
* 解密
*
* @param data SM2密文,实际包含三部分:ECC公钥、真正的密文、公钥和原文的SM3-HASH值
* @param privateKey 私钥
* @return 解密后的bytes
* @throws CryptException 异常
*/
public static byte[] decrypt(byte[] data, byte[] privateKey) throws CryptException {
return decrypt(data, ECKeyUtil.toSm2PrivateParams(privateKey));
}
// --------------------------------------------------------------------------------- Sign and Verify
/**
* 用私钥对信息生成数字签名
*
* @param data 加密数据
* @param privateKey 私钥
* @return 签名
*/
public byte[] sign(byte[] data, byte[] privateKey) {
return sign(data, privateKey, null);
}
/**
* 用私钥对信息生成数字签名
*
* @param data 被签名的数据数据
* @param privateKey 私钥
* @param id 可以为null,若为null,则默认withId为字节数组:"1234567812345678".getBytes()
* @return 签名
*/
public byte[] sign(byte[] data, byte[] privateKey, byte[] id) {
final SM2Signer signer = getSigner();
try {
CipherParameters param = new ParametersWithRandom(ECKeyUtil.toSm2PrivateParams(privateKey));
if (id != null) {
param = new ParametersWithID(param, id);
}
signer.init(true, param);
signer.update(data, 0, data.length);
return signer.generateSignature();
} catch (org.bouncycastle.crypto.CryptoException e) {
throw new CryptException(e);
}
}
/**
* 用公钥检验数字签名的合法性
*
* @param data 签名后的数据
* @param sign 签名
* @param publicKey 公钥
* @return 是否验证通过
*/
public boolean verify(byte[] data, byte[] sign,byte[] publicKey) {
return verify(data, sign, publicKey,null);
}
/**
* 用公钥检验数字签名的合法性
*
* @param data 数据签名后的数据
* @param sign 签名
* @param id 可以为null,若为null,则默认withId为字节数组:"1234567812345678".getBytes()
* @return 是否验证通过
*/
public boolean verify(byte[] data, byte[] sign,byte[] publicKey, byte[] id) {
final SM2Signer signer = getSigner();
CipherParameters param = ECKeyUtil.toSm2PublicParams(publicKey);
if (id != null) {
param = new ParametersWithID(param, id);
}
signer.init(false, param);
signer.update(data, 0, data.length);
return signer.verifySignature(sign);
}
// ------------------------------------------------------------------------------------------------------------------------- Private method start
/**
* 获取{@link SM2Engine},此对象为懒加载模式
*
* @return {@link SM2Engine}
*/
private static SM2Engine getEngine() {
Digest digest = new SM3Digest();
SM2Engine.Mode mode = SM2Engine.Mode.C1C3C2;
return new SM2Engine(digest, mode);
}
/**
* 获取{@link SM2Signer},此对象为懒加载模式
*
* @return {@link SM2Signer}
*/
private static SM2Signer getSigner() {
DSAEncoding encoding = StandardDSAEncoding.INSTANCE;
Digest digest = new SM3Digest();
return new SM2Signer(encoding, digest);
}
// ------------------------------------------------------------------------------------------------------------------------- Private method end
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy