使用Sm2進行簽名驗籤

需要的jar包

bcprov-jdk15on-1.59.jar

commons-lang3-3.1.jar

代碼

package com.ggp.sqy42d;

import org.bouncycastle.asn1.gm.GMNamedCurves;
import org.bouncycastle.asn1.gm.GMObjectIdentifiers;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec;

import java.security.*;


/**
 * @author: ggp
 * @Date: 2019/3/18 18:45
 * @Description:
 */
public class SM2Util {

    public static Signature signature;
    public static KeyPair keyPair;

    public static KeyPair getKeyPair() {
        return keyPair;
    }

    public static void setKeyPair(KeyPair keyPair) {
        SM2Util.keyPair = keyPair;
    }
    public static void createKeyPair(){
        // 獲取SM2 橢圓曲線推薦參數
        X9ECParameters ecParameters = GMNamedCurves.getByName("sm2p256v1");
        // 構造EC 算法參數
        ECNamedCurveParameterSpec sm2Spec = new ECNamedCurveParameterSpec(
                // 設置SM2 算法的 OID
                GMObjectIdentifiers.sm2p256v1.toString()
                // 設置曲線方程
                , ecParameters.getCurve()
                // 橢圓曲線G點
                , ecParameters.getG()
                // 大整數N
                , ecParameters.getN());
        try {
            // 創建 密鑰對生成器
            KeyPairGenerator gen = KeyPairGenerator.getInstance("EC", new BouncyCastleProvider());
            // 使用SM2的算法區域初始化密鑰生成器
            gen.initialize(sm2Spec, new SecureRandom());
            // 獲取密鑰對
            SM2Util.keyPair = gen.generateKeyPair();
        }catch (Exception e){
            e.printStackTrace();
        }
    }
    static {
        try {
            signature = Signature.getInstance(GMObjectIdentifiers.sm2sign_with_sm3.toString(),new BouncyCastleProvider());
            System.out.println(GMObjectIdentifiers.sm2sign_with_sm3.toString());
            createKeyPair();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
    }

    /**
     * 簽名
     * @param privateKey 簽名私鑰
     * @param plainText 明文
     * @return
     */
    public static String encrypt(PrivateKey privateKey,String plainText){

        try {
            signature.initSign(privateKey);
            signature.update(plainText.getBytes());
            byte[] bytes = signature.sign();
            return new String(bytes,0,bytes.length,"ISO-8859-1");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }


    /**
     * 驗證簽名
     * @param publicKey 簽名公鑰
     * @param signResult 簽名結果
     * @param plainText  明文
     * @return
     */
    public static boolean verify(PublicKey publicKey,byte[] signResult,String plainText){
        boolean result = false;
        try {
            signature.initVerify(publicKey);
            signature.update(plainText.getBytes());
            result = signature.verify(signResult);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    public static void main(String[] args) {
        String ss = SM2Util.encrypt(keyPair.getPrivate(),"111");
        try {
            System.out.println(ss);
            String ab = SM3Util.bytesToHexString(ss.getBytes("ISO-8859-1"));
            byte[] c = SM3Util.hexStringToBytes(ab);
            System.out.println(SM3Util.bytesToHexString(ss.getBytes("ISO-8859-1")));
            System.out.println(SM2Util.verify(keyPair.getPublic(), new String(c,"ISO-8859-1").getBytes("ISO-8859-1"), "111"));
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

需要注意的問題

new String 和 String.getBytes()如果沒有指定字符集,默認使用的是utf-8,utf-8會用一個或多個字節去表示一個字符,所以得到的結果會不同,因爲沒有牽涉到漢子,所以我們用ISO-8859-1字符集即可,我會在另一篇博客去敘述這個問題

https://blog.csdn.net/qq_33543634/article/details/88740524

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