基於BC實現的(JAVA版)SM2國密算法簽名驗籤DEMO

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;
  }
 }





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章