天天看點

基于BC實作的(JAVA版)SM2國密算法簽名驗簽DEMO

POM 片段:

  <dependencies>

 <dependency>

     <groupId>org.bouncycastle</groupId>

     <artifactId>bcprov-jdk15on</artifactId>

     <version>1.60</version>

 </dependency>

     <artifactId>bcpkix-jdk15on</artifactId>

</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);

     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;

  }