依赖
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15to18</artifactId>
<version>1.69</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.10</version>
</dependency>
代码
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.HexUtil;
import cn.hutool.crypto.BCUtil;
import cn.hutool.crypto.SmUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.SM2;
import cn.hutool.core.codec.Base64;
import org.bouncycastle.asn1.*;
import org.bouncycastle.asn1.gm.GMNamedCurves;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
import org.bouncycastle.math.ec.ECPoint;
import java.io.IOException;
import java.math.BigInteger;
import java.util.Arrays;
public class SM2Util {
private static final int C1_LEN = 65;
private static final int C3_LEN = 32;
public static byte[] changeC1C3C2ToAsn1(byte[] c1c3c2) throws IOException {
byte[] c1 = Arrays.copyOfRange(c1c3c2, 0, C1_LEN);
byte[] c3 = Arrays.copyOfRange(c1c3c2, C1_LEN, C1_LEN + C3_LEN);
byte[] c2 = Arrays.copyOfRange(c1c3c2, C1_LEN + C3_LEN, c1c3c2.length);
byte[] c1X = Arrays.copyOfRange(c1, 1, 33);
byte[] c1Y = Arrays.copyOfRange(c1, 33, 65);
BigInteger r = new BigInteger(1, c1X);
BigInteger s = new BigInteger(1, c1Y);
ASN1Integer x = new ASN1Integer(r);
ASN1Integer y = new ASN1Integer(s);
DEROctetString derDig = new DEROctetString(c3);
DEROctetString derEnc = new DEROctetString(c2);
ASN1EncodableVector v = new ASN1EncodableVector();
v.add(x);
v.add(y);
v.add(derDig);
v.add(derEnc);
DERSequence seq = new DERSequence(v);
return seq.getEncoded(ASN1Encoding.DER);
}
public static byte[] changeAsn1ToC1C3C2(byte[] asn1) throws IOException {
ASN1InputStream aIn = new ASN1InputStream(asn1);
ASN1Sequence seq = (ASN1Sequence) aIn.readObject();
BigInteger x = ASN1Integer.getInstance(seq.getObjectAt(0)).getValue();
BigInteger y = ASN1Integer.getInstance(seq.getObjectAt(1)).getValue();
byte[] c3 = ASN1OctetString.getInstance(seq.getObjectAt(2)).getOctets();
byte[] c2 = ASN1OctetString.getInstance(seq.getObjectAt(3)).getOctets();
ECPoint c1Point = GMNamedCurves.getByName("sm2p256v1").getCurve().createPoint(x, y);
byte[] c1 = c1Point.getEncoded(false);
return ArrayUtil.addAll(c1, c3, c2);
}
public static void main(String[] args) throws IOException {
String text = "1111";
SM2 sm2 = SmUtil.sm2();
byte[] publicKey = ((BCECPublicKey) sm2.getPublicKey()).getQ().getEncoded(false);
byte[] privateKey = BCUtil.encodeECPrivateKey(sm2.getPrivateKey());
System.out.println("公钥: " + HexUtil.encodeHexStr(publicKey));
System.out.println("私钥: " + HexUtil.encodeHexStr(privateKey));
SM2 sm2Test = SmUtil.sm2(privateKey, publicKey);
byte[] encrypt = sm2Test.encrypt(text, KeyType.PublicKey);
byte[] bytes = changeC1C3C2ToAsn1(encrypt);
String encryptData = Base64.encode(bytes);
System.out.println("加密后:"+encryptData);
byte[] asn1 = Base64.decode(encryptData);
byte[] c1c3c2 = changeAsn1ToC1C3C2(asn1);
byte[] decryptData = sm2Test.decrypt(c1c3c2, KeyType.PrivateKey);
System.out.println("解密后:"+new String(decryptData));
byte[] sign = sm2Test.sign(text.getBytes());
String signText = Base64.encode(sign);
System.out.println("签名:"+ signText);
boolean verify = sm2Test.verify(text.getBytes(), Base64.decode(signText));
System.out.println("验签结果::"+ verify);
}
}