POM 片段:
<dependencies>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.60</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk15on</artifactId>
<version>1.60</version>
</dependency>
</dependencies>
JAVA代碼片段:
import java.io.FileInputStream;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.SecureRandom;
import java.security.Security;
import java.security.Signature;
import java.util.Enumeration;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
public class TestClass {
public static void main(String[] args) throws Exception{
String orgData = "123123123";
String algorithm = "SM3withSM2";
String pfxFile = "./sm2.pfx";//sm2證書對應的pfx
String password = "12345678"; //pfx訪問密碼
Security.addProvider(new BouncyCastleProvider());
FileInputStream fis = new FileInputStream(pfxFile);
KeyStore ks2 = KeyStore.getInstance("PKCS12", "BC");
ks2.load(fis, password.toCharArray());
Enumeration enum1 = ks2.aliases();
String keyAlias = null;
if (enum1.hasMoreElements())
{
keyAlias = (String)enum1.nextElement();
}
Signature sig = Signature.getInstance(algorithm, "BC");
sig.initSign((PrivateKey) ks2.getKey(keyAlias, null), new SecureRandom());
sig.update(orgData.getBytes());
byte[] rs = sig.sign();
}
}
如果直接運行以上代碼,會報錯,需要加入JCE到 jdk中。
具體解析見:http://www.oracle.com/technetwork/java/javase/tech/index-jsp-136007.html
不同jdk版本下載地址:
https://www.oracle.com/technetwork/java/javase/downloads/jce-all-download-5170447.html
具體操作是下載下來的local_policy.jar,US_export_policy.jar 兩個jar 包放到 jdkhome\jre\lib\security 目錄下即可。
附驗籤方法:
public static boolean sm2VerifySignedData(byte[] oriData, String signCert, String signValue) {
try {
//獲取CA證書中的公鑰
byte[] signCertBytes = ServiceHelper.sunBase64Decode(signCert);
ASN1Sequence signCertSeq = ASN1Sequence.getInstance(signCertBytes);
ASN1Sequence tbsCertSeq = (ASN1Sequence) signCertSeq.getObjectAt(0);
TBSCertificate tbsCaCert = TBSCertificate.getInstance(tbsCertSeq);
SubjectPublicKeyInfo issuerPublicKeyInfo = tbsCaCert.getSubjectPublicKeyInfo();
DERBitString serverPubBit = issuerPublicKeyInfo.getPublicKeyData();
byte[] rawPub = serverPubBit.getBytes();
// System.out.println("rawPub len:" + rawPub.length);
// System.out.println(Hex.toHexString(rawPub));
byte[] rawPub2 = new byte[64];
System.arraycopy(rawPub, rawPub.length-64, rawPub2, 0, 64);
// System.out.println(Hex.toHexString(rawPub2));
byte[] signValue2 = null;
byte[] signValueBytes = sunBase64Decode(signValue);
if (signValueBytes==null) {
return false;
}
if (signValueBytes.length>64 && signValueBytes[0]==0x30) {
//標準的SM2簽名值,DER結構。
ASN1Sequence signSeq = ASN1Sequence.getInstance(signValueBytes);
ASN1Integer r = (ASN1Integer) signSeq.getObjectAt(0);
ASN1Integer s = (ASN1Integer) signSeq.getObjectAt(1);
byte[] rBytes1 = r.getPositiveValue().toByteArray();
byte[] rBytes = new byte[32];
if (rBytes1.length < 32) {
System.arraycopy(rBytes1, 0, rBytes, 32-rBytes1.length, rBytes1.length);
} else {
System.arraycopy(rBytes1, rBytes1.length-32, rBytes, 0, 32);
}
byte[] sBytes1 = s.getPositiveValue().toByteArray();
byte[] sBytes = new byte[32];
if (sBytes1.length < 32) {
System.arraycopy(sBytes1, 0, sBytes, 32-sBytes1.length, sBytes1.length);
} else {
System.arraycopy(sBytes1, sBytes1.length-32, sBytes, 0, 32);
}
signValue2 = new byte[64];
System.arraycopy(rBytes, rBytes.length-32, signValue2, 0, 32);
System.arraycopy(sBytes, sBytes.length-32, signValue2, 32, 32);
} else {
//非標準的SM2簽名值,只有R和S拼接起來的64字節。
signValue2 = signValueBytes;
}
SM2 sm2 = SM2.Instance();
boolean verify = sm2.Verify(oriData, signValue2, rawPub2);
// System.out.println(verify + "");
return verify;
} catch (Exception e) {
debugLog.error("", e);
return false;
}
}