当前位置: 首页 > 工具软件 > Bouncy Castle > 使用案例 >

java bouncycastle_Java国密相关算法(bouncycastle)

平庆
2023-12-01

packagecom.pcidata.common.tools.encrypt;importcom.pcidata.common.tools.CommonUtils;importcom.pcidata.common.tools.CustomStringUtils;importcom.pcidata.modules.key.modelvo.response.PCIKeyPair;importlombok.extern.slf4j.Slf4j;importorg.bouncycastle.asn1.gm.GMNamedCurves;importorg.bouncycastle.asn1.x9.X9ECParameters;importorg.bouncycastle.crypto.AsymmetricCipherKeyPair;importorg.bouncycastle.crypto.engines.SM2Engine;importorg.bouncycastle.crypto.generators.ECKeyPairGenerator;import org.bouncycastle.crypto.params.*;importorg.bouncycastle.crypto.signers.SM2Signer;importorg.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey;importorg.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;importorg.bouncycastle.jce.spec.ECParameterSpec;importorg.bouncycastle.math.ec.ECPoint;importorg.bouncycastle.pqc.math.linearalgebra.ByteUtils;importorg.bouncycastle.util.Strings;importorg.bouncycastle.util.encoders.Hex;importjava.math.BigInteger;importjava.security.NoSuchAlgorithmException;importjava.security.PrivateKey;importjava.security.PublicKey;importjava.security.SecureRandom;/*** @Author: dzy

* @Date: 2018/9/28 15:53

* @Describe: SM2工具类*/@Slf4jpublic classSM2Util {/*** 生成SM2公私钥对

*@return

*/

private staticAsymmetricCipherKeyPair genKeyPair0() {//获取一条SM2曲线参数

X9ECParameters sm2ECParameters = GMNamedCurves.getByName("sm2p256v1");//构造domain参数

ECDomainParameters domainParameters = newECDomainParameters(sm2ECParameters.getCurve(),

sm2ECParameters.getG(), sm2ECParameters.getN());//1.创建密钥生成器

ECKeyPairGenerator keyPairGenerator = newECKeyPairGenerator();//2.初始化生成器,带上随机数

try{

keyPairGenerator.init(new ECKeyGenerationParameters(domainParameters, SecureRandom.getInstance("SHA1PRNG")));

}catch(NoSuchAlgorithmException e) {

log.error("生成公私钥对时出现异常:", e);//e.printStackTrace();

}//3.生成密钥对

AsymmetricCipherKeyPair asymmetricCipherKeyPair =keyPairGenerator.generateKeyPair();returnasymmetricCipherKeyPair;

}/*** 生成公私钥对(默认压缩公钥)

*@return

*/

public staticPCIKeyPair genKeyPair() {return genKeyPair(true);

}/*** 生成公私钥对

*@paramcompressedPubKey 是否压缩公钥

*@return

*/

public static PCIKeyPair genKeyPair(booleancompressedPubKey) {

AsymmetricCipherKeyPair asymmetricCipherKeyPair=genKeyPair0();//提取公钥点

ECPoint ecPoint =((ECPublicKeyParameters) asymmetricCipherKeyPair.getPublic()).getQ();//公钥前面的02或者03表示是压缩公钥,04表示未压缩公钥,04的时候,可以去掉前面的04

String pubKey =Hex.toHexString(ecPoint.getEncoded(compressedPubKey));

BigInteger privatekey=((ECPrivateKeyParameters) asymmetricCipherKeyPair.getPrivate()).getD();

String priKey= privatekey.toString(16);

PCIKeyPair keyPair= newPCIKeyPair(priKey, pubKey);returnkeyPair;

}/*** 私钥签名

*@paramprivateKey 私钥

*@paramcontent 待签名内容

*@return

*/

public staticString sign(String privateKey, String content) {//待签名内容转为字节数组

byte[] message =Hex.decode(content);//获取一条SM2曲线参数

X9ECParameters sm2ECParameters = GMNamedCurves.getByName("sm2p256v1");//构造domain参数

ECDomainParameters domainParameters = newECDomainParameters(sm2ECParameters.getCurve(),

sm2ECParameters.getG(), sm2ECParameters.getN());

BigInteger privateKeyD= new BigInteger(privateKey, 16);

ECPrivateKeyParameters privateKeyParameters= newECPrivateKeyParameters(privateKeyD, domainParameters);//创建签名实例

SM2Signer sm2Signer = newSM2Signer();//初始化签名实例,带上ID,国密的要求,ID默认值:1234567812345678

try{

sm2Signer.init(true, new ParametersWithID(new ParametersWithRandom(privateKeyParameters, SecureRandom.getInstance("SHA1PRNG")), Strings.toByteArray("1234567812345678")));

}catch(NoSuchAlgorithmException e) {

log.error("签名时出现异常:", e);

}//生成签名,签名分为两部分r和s,分别对应索引0和1的数组

BigInteger[] bigIntegers =sm2Signer.generateSignature(message);byte[] rBytes = modifyRSFixedBytes(bigIntegers[0].toByteArray());byte[] sBytes = modifyRSFixedBytes(bigIntegers[1].toByteArray());byte[] signBytes =ByteUtils.concatenate(rBytes, sBytes);

String sign=Hex.toHexString(signBytes);returnsign;

}/*** 将R或者S修正为固定字节数

*@paramrs

*@return

*/

private static byte[] modifyRSFixedBytes(byte[] rs) {int length =rs.length;int fixedLength = 32;byte[] result = new byte[fixedLength];if (length < 32) {

System.arraycopy(rs,0, result, fixedLength -length, length);

}else{

System.arraycopy(rs, length- fixedLength, result, 0, fixedLength);

}returnresult;

}/*** 验证签名

*@parampublicKey 公钥

*@paramcontent 待签名内容

*@paramsign 签名值

*@return

*/

public static booleanverify(String publicKey, String content, String sign) {//待签名内容

byte[] message =Hex.decode(content);byte[] signData =Hex.decode(sign);//获取一条SM2曲线参数

X9ECParameters sm2ECParameters = GMNamedCurves.getByName("sm2p256v1");//构造domain参数

ECDomainParameters domainParameters = newECDomainParameters(sm2ECParameters.getCurve(),

sm2ECParameters.getG(),

sm2ECParameters.getN());//提取公钥点

ECPoint pukPoint =sm2ECParameters.getCurve().decodePoint(CommonUtils.hexString2byte(publicKey));//公钥前面的02或者03表示是压缩公钥,04表示未压缩公钥, 04的时候,可以去掉前面的04

ECPublicKeyParameters publicKeyParameters = newECPublicKeyParameters(pukPoint, domainParameters);//获取签名

BigInteger R = null;

BigInteger S= null;byte[] rBy = new byte[33];

System.arraycopy(signData,0, rBy, 1, 32);

rBy[0] = 0x00;byte[] sBy = new byte[33];

System.arraycopy(signData,32, sBy, 1, 32);

sBy[0] = 0x00;

R= newBigInteger(rBy);

S= newBigInteger(sBy);//创建签名实例

SM2Signer sm2Signer = newSM2Signer();

ParametersWithID parametersWithID= new ParametersWithID(publicKeyParameters, Strings.toByteArray("1234567812345678"));

sm2Signer.init(false, parametersWithID);//验证签名结果

boolean verify =sm2Signer.verifySignature(message, R, S);returnverify;

}/*** SM2加密算法

*@parampublicKey 公钥

*@paramdata 数据

*@return

*/

public staticString encrypt(String publicKey, String data){//获取一条SM2曲线参数

X9ECParameters sm2ECParameters = GMNamedCurves.getByName("sm2p256v1");//构造domain参数

ECDomainParameters domainParameters = newECDomainParameters(sm2ECParameters.getCurve(),

sm2ECParameters.getG(),

sm2ECParameters.getN());//提取公钥点

ECPoint pukPoint =sm2ECParameters.getCurve().decodePoint(CommonUtils.hexString2byte(publicKey));//公钥前面的02或者03表示是压缩公钥,04表示未压缩公钥, 04的时候,可以去掉前面的04

ECPublicKeyParameters publicKeyParameters = newECPublicKeyParameters(pukPoint, domainParameters);

SM2Engine sm2Engine= newSM2Engine();

sm2Engine.init(true, new ParametersWithRandom(publicKeyParameters, newSecureRandom()));byte[] arrayOfBytes = null;try{byte[] in = data.getBytes("utf-8");

arrayOfBytes= sm2Engine.processBlock(in, 0, in.length);

}catch(Exception e) {

log.error("SM2加密时出现异常:", e);

}returnHex.toHexString(arrayOfBytes);

}/*** SM2加密算法

*@parampublicKey 公钥

*@paramdata 明文数据

*@return

*/

public staticString encrypt(PublicKey publicKey, String data) {

ECPublicKeyParameters ecPublicKeyParameters= null;if (publicKey instanceofBCECPublicKey) {

BCECPublicKey bcecPublicKey=(BCECPublicKey) publicKey;

ECParameterSpec ecParameterSpec=bcecPublicKey.getParameters();

ECDomainParameters ecDomainParameters= newECDomainParameters(ecParameterSpec.getCurve(),

ecParameterSpec.getG(), ecParameterSpec.getN());

ecPublicKeyParameters= newECPublicKeyParameters(bcecPublicKey.getQ(), ecDomainParameters);

}

SM2Engine sm2Engine= newSM2Engine();

sm2Engine.init(true, new ParametersWithRandom(ecPublicKeyParameters, newSecureRandom()));byte[] arrayOfBytes = null;try{byte[] in = data.getBytes("utf-8");

arrayOfBytes= sm2Engine.processBlock(in,0, in.length);

}catch(Exception e) {

log.error("SM2加密时出现异常:", e);

}returnHex.toHexString(arrayOfBytes);

}/*** SM2解密算法

*@paramprivateKey 私钥

*@paramcipherData 密文数据

*@return

*/

public staticString decrypt(String privateKey, String cipherData) {byte[] cipherDataByte =Hex.decode(cipherData);//获取一条SM2曲线参数

X9ECParameters sm2ECParameters = GMNamedCurves.getByName("sm2p256v1");//构造domain参数

ECDomainParameters domainParameters = newECDomainParameters(sm2ECParameters.getCurve(),

sm2ECParameters.getG(), sm2ECParameters.getN());

BigInteger privateKeyD= new BigInteger(privateKey, 16);

ECPrivateKeyParameters privateKeyParameters= newECPrivateKeyParameters(privateKeyD, domainParameters);

SM2Engine sm2Engine= newSM2Engine();

sm2Engine.init(false, privateKeyParameters);

String result= null;try{byte[] arrayOfBytes = sm2Engine.processBlock(cipherDataByte, 0, cipherDataByte.length);return new String(arrayOfBytes, "utf-8");

}catch(Exception e) {

log.error("SM2解密时出现异常:", e);

}returnresult;

}/*** SM2解密算法

*@paramprivateKey 私钥

*@paramcipherData 密文数据

*@return

*/

public staticString decrypt(PrivateKey privateKey, String cipherData) {byte[] cipherDataByte =Hex.decode(cipherData);

BCECPrivateKey bcecPrivateKey=(BCECPrivateKey) privateKey;

ECParameterSpec ecParameterSpec=bcecPrivateKey.getParameters();

ECDomainParameters ecDomainParameters= newECDomainParameters(ecParameterSpec.getCurve(),

ecParameterSpec.getG(), ecParameterSpec.getN());

ECPrivateKeyParameters ecPrivateKeyParameters= newECPrivateKeyParameters(bcecPrivateKey.getD(),

ecDomainParameters);

SM2Engine sm2Engine= newSM2Engine();

sm2Engine.init(false, ecPrivateKeyParameters);

String result= null;try{byte[] arrayOfBytes = sm2Engine.processBlock(cipherDataByte, 0, cipherDataByte.length);return new String(arrayOfBytes, "utf-8");

}catch(Exception e) {

log.error("SM2解密时出现异常:", e);

}returnresult;

}/*** 将未压缩公钥压缩成压缩公钥

*@parampubKey 未压缩公钥(16进制,不要带头部04)

*@return

*/

public staticString compressPubKey(String pubKey) {

pubKey= CustomStringUtils.append("04", pubKey); //将未压缩公钥加上未压缩标识.//获取一条SM2曲线参数

X9ECParameters sm2ECParameters = GMNamedCurves.getByName("sm2p256v1");//构造domain参数

ECDomainParameters domainParameters = newECDomainParameters(sm2ECParameters.getCurve(),

sm2ECParameters.getG(),

sm2ECParameters.getN());//提取公钥点

ECPoint pukPoint =sm2ECParameters.getCurve().decodePoint(CommonUtils.hexString2byte(pubKey));//公钥前面的02或者03表示是压缩公钥,04表示未压缩公钥, 04的时候,可以去掉前面的04//ECPublicKeyParameters publicKeyParameters = new ECPublicKeyParameters(pukPoint, domainParameters);

String compressPubKey=Hex.toHexString(pukPoint.getEncoded(Boolean.TRUE));returncompressPubKey;

}/*** 将压缩的公钥解压为非压缩公钥

*@paramcompressKey 压缩公钥

*@return

*/

public staticString unCompressPubKey(String compressKey) {//获取一条SM2曲线参数

X9ECParameters sm2ECParameters = GMNamedCurves.getByName("sm2p256v1");//构造domain参数

ECDomainParameters domainParameters = newECDomainParameters(sm2ECParameters.getCurve(),

sm2ECParameters.getG(),

sm2ECParameters.getN());//提取公钥点

ECPoint pukPoint =sm2ECParameters.getCurve().decodePoint(CommonUtils.hexString2byte(compressKey));//公钥前面的02或者03表示是压缩公钥,04表示未压缩公钥, 04的时候,可以去掉前面的04//ECPublicKeyParameters publicKeyParameters = new ECPublicKeyParameters(pukPoint, domainParameters);

String pubKey=Hex.toHexString(pukPoint.getEncoded(Boolean.FALSE));

pubKey= pubKey.substring(2); //去掉前面的04 (04的时候,可以去掉前面的04)

returnpubKey;

}

}

 类似资料: