JAVA:JNA方式调用USBKey SKF接口实现SM2证书的PKCS1格式签名和验证 实验总结_20220111_七侠镇莫尛貝

目标:JAVA通过JNA调用USBKey的SKF接口,实现SM2证书的PKCS1格式签名和验证

环境:usbkey型号:龙脉gm3000

skf库:mtoken_gm3000_dky.dll  x86版,产品版本 1,1,19,1

开发环境:IDEA 14,  JDK1.8x86  (如果使用JDK x64,需要更换64位的skf库)

难点:SKF C 语言接口的某些输入输出参数(如ECCPUBLICKEYBLOB,ECCSIGNATUREBLOB),需要参考skf.h 转换成Java的struct结构

代码:

package com.terry.skf;

import com.terry.skf.struct.*;
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.ptr.ByteByReference;
import com.sun.jna.ptr.LongByReference;
import com.sun.jna.ptr.PointerByReference;

/**
 * Created by Administrator on 2021/12/1 0001.
 */
public interface CLibrary extends Library {
        public static final String SKF_DLL_PATH ="D:/Java/program_2021_java/demo_skf_jni/dll/mtoken_gm3000_dky";
        //CLibrary INSTANCE = (CLibrary) Native.loadLibrary(SKF_DLL_PATH, CLibrary.class);
        CLibrary INSTANCE = (CLibrary) Native.load(SKF_DLL_PATH, CLibrary.class);

        int SKF_EnumDev(boolean input, ByteByReference out, LongByReference len);
        //int SKF_EnumDev(boolean input, PointerByReference out, LongByReference len);

        int SKF_ConnectDev(String input, PointerByReference hDev);
        int SKF_EnumApplication(Pointer hDev, ByteByReference szAppName, LongByReference pulSize);

        int SKF_OpenApplication(Pointer hDev, String pappname, PointerByReference happ);
        int SKF_VerifyPIN(Pointer hApplication, int ulPINType, String szPIN, LongByReference pulRetryCount);

        int SKF_EnumContainer(Pointer hApplication, Struct_CONTAINER szContainerName, LongByReference pulSize);
        //int SKF_EnumContainer(Pointer hApplication, PointerByReference szContainerName, String pulSize);
        //int SKF_EnumContainer(Pointer hApplication, Struct_CONTAINER szContainerName, String pulSize);

        int SKF_OpenContainer(Pointer hApplication, String szContainerName, PointerByReference phContainer);
        int SKF_GetContainerType(Pointer phContainer, LongByReference pulContainerType);
        int SKF_ExportPublicKey(Pointer hContainer, boolean bSignFlag, Struct_ECCPUBLICKEYBLOB pbBlob, LongByReference pulBlobLen);
        int SKF_ExportCertificate(Pointer hContainer, boolean bSignFlag, Struct_ECCCERTBLOB pbCert, LongByReference pulCertLen);
        int SKF_DigestInit(Pointer hdev, int alg_hash, Struct_ECCPUBLICKEYBLOB ecc_pub, String pubid, int ulIDLen, PointerByReference hHash);

        int SKF_Digest(Pointer hHash, String pbData, int ulDataLen, Struct_SM3BLOB pbHashData, LongByReference pulHashLen);
        int SKF_Digest(Pointer hHash, byte[] pbData, int ulDataLen, Struct_SM3BLOB pbHashData, LongByReference pulHashLen);
        int SKF_Digest(Pointer hHash, byte[] pbData, int ulDataLen, Struct_SM3BLOB pbHashData, int pulHashLen);

        int SKF_ECCSignData(Pointer hContainer, Struct_SM3BLOB pbData, int ulDataLen, Struct_ECCSIGNATUREBLOB pSignature);

        int SKF_ECCVerify(Pointer hDev, Struct_ECCPUBLICKEYBLOB pECCPubKeyBlob, Struct_SM3BLOB pbData, int ulDataLen, Struct_ECCSIGNATUREBLOB pSignature);

        int SKF_DisConnectDev(Pointer hDev);
        int SKF_CloseContainer(Pointer hcont);
        int SKF_CloseApplication(Pointer hApplication);
        int SKF_CloseHandle(Pointer hkey);
    }

package com.terry.skf;

// https://www.jianshu.com/p/dceae90f8537
import com.terry.skf.struct.*;
import com.sun.jna.Pointer;
import com.sun.jna.ptr.ByteByReference;
import com.sun.jna.ptr.LongByReference;
import com.sun.jna.ptr.PointerByReference;
import com.terry.skf.tool.Util;

import java.util.List;

public class SKF_TOOL {
    private static String userid = "1234567812345678";
    private Pointer p_hdev = null;
    private Pointer p_happ = null;
    private Pointer p_hcont = null;
    private Pointer p_phHash = null;

    private CLibrary ukey = CLibrary.INSTANCE;
    private String USER_PIN = "111111";

    public  SKF_TOOL(String user_pin) {
        USER_PIN = user_pin;
        int ret = -1 ;
        int alg_hash = 1;
        int APP_NAME_SIZE = 256;

        Util.blue("============SKF_TOOL init...==================");
        try{
            LongByReference lbr = new LongByReference();
            ret = ukey.SKF_EnumDev(true,null,lbr);
            long lv = lbr.getPointer().getLong(0);
            Util.blue(ret + " SKF_EnumDev 设备编号长度= [" + lv + "]");
            if(lv == 0){
                System.out.println("未插入USBKey!");
                return ;
            }

            ByteByReference bbr = new ByteByReference();
            LongByReference lbr_input = new LongByReference();
            lbr_input.setValue(lv);
            ret = ukey.SKF_EnumDev(true, bbr, lbr_input);
            String str_dev = bbr.getPointer().getString(0);
            Util.blue(ret + " SKF_EnumDev 设备编号= [" + str_dev + "]");

            PointerByReference lbr_hdev = new PointerByReference();
            ret = ukey.SKF_ConnectDev(str_dev, lbr_hdev);
            p_hdev = lbr_hdev.getValue();
            Util.blue(ret + " SKF_ConnectDev 设备hdev= [" + p_hdev + "]");

            ByteByReference bbr_applist = new ByteByReference();
            LongByReference lbr_pulSize = new LongByReference();
            lbr_pulSize.setValue(APP_NAME_SIZE);
            ret = ukey.SKF_EnumApplication(p_hdev, bbr_applist, lbr_pulSize);
            // Fuck!: bbr_applist最后有个空格!需要去掉!
            String app_name = bbr_applist.getPointer().getString(0).trim();
            Util.blue(ret + " SKF_EnumApplication app name= [" + app_name + "]");

            PointerByReference pbr_happ = new PointerByReference();
            ret = ukey.SKF_OpenApplication(p_hdev, app_name, pbr_happ);
            p_happ = pbr_happ.getValue();
            Util.blue(ret + " SKF_OpenApplication app handle = [" + p_happ + "]");

            LongByReference lbr_pulRetryCount = new LongByReference();
            ret = ukey.SKF_VerifyPIN(p_happ, 1, USER_PIN,lbr_pulRetryCount);
            Util.blue(ret + " SKF_VerifyPIN 重试次数 = [" + lbr_pulRetryCount.getValue() + "]");
            if(ret != 0){
                Util.red("SKF_VerifyPIN fail!");
                //throw new Exception("SKF_VerifyPIN fail!");
                System.out.println("SKF_VerifyPIN fail!");
            }
        }catch (Exception exp){
            exp.printStackTrace();
        }
        Util.blue("p_hdev =" + p_hdev);
        Util.blue("p_happ =" + p_happ);
        Util.blue("============SKF_TOOL init end.==================\r\n");
        return ;
    }
    public void close() {
        int ret = -1;
        Util.blue("\r\n============SKF_TOOL close...==================");
        try{
            if(p_phHash != null) {
                ret = ukey.SKF_CloseHandle(p_phHash);
                Util.blue("SKF_CloseHandle " + ret);
            }
            if(p_hcont != null){
                ret = ukey.SKF_CloseContainer(p_hcont);
                Util.blue("SKF_CloseContainer " + ret );
            }
            if(p_happ != null){
                ret = ukey.SKF_CloseApplication(p_happ);
                Util.blue("SKF_CloseApplication "+ ret );
            }
            if(p_hdev != null){
                ret = ukey.SKF_DisConnectDev(p_hdev);
                Util.blue("SKF_DisConnectDev "+ ret );
            }
        }catch (Exception exp){
            exp.printStackTrace();
        }
        Util.blue("============SKF_TOOL close end.==================");
        return  ;
    }

    public String sm3_no_userid(String text_plain) {
        return sm3_no_userid( text_plain,"utf-8");
    }
    public String sm3_no_userid(String text_plain,String charsetName) {
        int ret;
        String sm3_b64 = "";
        int alg_hash = 1;
        Util.blue("============SKF_TOOL SM3 Hash_no_userid ...==================");
        try {
            PointerByReference pbr_phHash = new PointerByReference();
            ret = ukey.SKF_DigestInit(p_hdev, alg_hash, null,null,0,pbr_phHash);
            p_phHash = pbr_phHash.getValue();
            Util.red(ret + " SKF_DigestInit Handle_hash = [" + p_phHash + "]");

            LongByReference lbr_pulHashLen = new LongByReference();
            ret = ukey.SKF_Digest(p_phHash, text_plain.getBytes(charsetName), text_plain.length(), null, lbr_pulHashLen);
            Util.red(ret + " SKF_Digest bbr_pbHashData size = [" + lbr_pulHashLen.getValue() + " bits ]");

            Struct_SM3BLOB pbr_pbHashData = new Struct_SM3BLOB();
            //lbr_pulHashLen.setValue(32);
            ret = ukey.SKF_Digest(p_phHash, text_plain.getBytes(charsetName), text_plain.length(), pbr_pbHashData, lbr_pulHashLen);
            sm3_b64 = pbr_pbHashData.get_sm3_b64();
            Util.red(ret + " SKF_Digest bbr_pbHashData SM3 Base64 = [" + sm3_b64 + "]");
        } catch (Exception exp) {
            exp.printStackTrace();
        }
        Util.blue("============SKF_TOOL SM3 Hash_no_userid end.==================\r\n");
        return sm3_b64;
    }

    public String sm3_with_userid(String text_plain) {
        return sm3_with_userid(text_plain,"utf-8");
    }
    public String sm3_with_userid(String text_plain, String charsetName) {
        int ret;
        String sm3_b64 = "";
        int alg_hash = 1;
        Util.blue("============SKF_TOOL SM3 Hash_with_userid ...==================");
        try {
            Struct_SM3BLOB pbr_pbHashData = sm3_with_userid_ex(text_plain, charsetName);

            LongByReference lbr_pulHashLen = new LongByReference();
            lbr_pulHashLen.setValue(256);

            ret = ukey.SKF_Digest(p_phHash, text_plain.getBytes(charsetName), text_plain.length(), pbr_pbHashData, lbr_pulHashLen);
            sm3_b64 = pbr_pbHashData.get_sm3_b64();
            Util.red(ret + " SKF_Digest bbr_pbHashData SM3 Base64 = [" + sm3_b64 + "]");
            return sm3_b64;
        } catch (Exception exp) {
            exp.printStackTrace();
        }
        Util.blue("============SKF_TOOL SM3 Hash_with_userid end.==================\r\n");
        return sm3_b64;
    }

    public Struct_SM3BLOB sm3_with_userid_ex(String text_plain, String charsetName) {
        int ret;
        String sm3_b64 = "";
        int alg_hash = 1;
        Struct_SM3BLOB pbr_pbHashData = null;

        Util.blue("============SKF_TOOL SM3 Hash_with_userid ...==================");
        try {
            LongByReference lbr_pulSize = new LongByReference();
            ret = ukey.SKF_EnumContainer(p_happ, null, lbr_pulSize);
            long pulSize = lbr_pulSize.getValue();
            Util.blue(ret + " SKF_EnumContainer 容器名大小 = [" + pulSize + "]");

            Struct_CONTAINER containers = new Struct_CONTAINER();
            ret = ukey.SKF_EnumContainer(p_happ, containers, lbr_pulSize);
            String cont_name = containers.getPointer().getString(0);
            Util.blue(ret + " SKF_EnumContainer 容器名 = [" + cont_name + "]");

            PointerByReference pbr_phContainer = new PointerByReference();
            ret = ukey.SKF_OpenContainer(p_happ, cont_name, pbr_phContainer);
            p_hcont = pbr_phContainer.getValue();
            Util.blue(ret + " SKF_OpenContainer 容器p_hcont = [" + p_hcont + "]");

            LongByReference lbr_pulContainerType = new LongByReference();
            ret = ukey.SKF_GetContainerType(p_hcont, lbr_pulContainerType);
            long pulContainerType = lbr_pulContainerType.getValue();
            Util.blue(ret + " SKF_GetContainerType 容器类型 (0表示未定、尚未分配类型或者为空容器,为1表示为RSA容器,为2表示为ECC容器。)= [" + pulContainerType + "]");
            if(pulContainerType == 2){
                alg_hash = 2;
            }

            LongByReference lbr_pulBlobLen = new LongByReference();
            ret = ukey.SKF_ExportPublicKey(p_hcont, false, null, lbr_pulBlobLen);
            long l_pulBlobLen = lbr_pulBlobLen.getValue();
            Util.red(ret + " SKF_ExportPublicKey 公钥大小 = [" + l_pulBlobLen + "]");

            Struct_ECCPUBLICKEYBLOB pubkey = new Struct_ECCPUBLICKEYBLOB();
            lbr_pulBlobLen.setValue(l_pulBlobLen);
            ret = ukey.SKF_ExportPublicKey(p_hcont, false, pubkey, lbr_pulBlobLen);
            Util.red(ret + " SKF_ExportPublicKey 公钥 bitlen= " + pubkey.get_BitLen());
            Util.red(ret + " SKF_ExportPublicKey 公钥x = [" + Util.bytesToHex(pubkey.XCoordinate) + "]");
            Util.red(ret + " SKF_ExportPublicKey 公钥y = [" + Util.bytesToHex(pubkey.YCoordinate) + "]");

            PointerByReference pbr_phHash = new PointerByReference();
            ret = ukey.SKF_DigestInit(p_hdev, alg_hash, pubkey, userid, userid.length(), pbr_phHash);
            p_phHash = pbr_phHash.getValue();
            Util.red(ret + " SKF_DigestInit Handle_hash = [" + p_phHash + "]");

            LongByReference lbr_pulHashLen = new LongByReference();
            ret = ukey.SKF_Digest(p_phHash, text_plain.getBytes(charsetName), text_plain.length(), null, lbr_pulHashLen);
            Util.red(ret + " SKF_Digest bbr_pbHashData size = [" + lbr_pulHashLen.getValue() + " bits ]");

            pbr_pbHashData = new Struct_SM3BLOB();
            ret = ukey.SKF_Digest(p_phHash, text_plain.getBytes(charsetName), text_plain.length(), pbr_pbHashData, lbr_pulHashLen);
            sm3_b64 = pbr_pbHashData.get_sm3_b64();
            Util.red(ret + " SKF_Digest bbr_pbHashData SM3 Base64 = [" + sm3_b64 + "]");
        } catch (Exception exp) {
            exp.printStackTrace();
        }
        Util.blue("============SKF_TOOL SM3 Hash_with_userid end.==================\r\n");
        return pbr_pbHashData;
    }

    public  Struct_ECCPUBLICKEYBLOB get_pubkey() {
        int ret ;
        String cert_p7 = "";
        Struct_ECCPUBLICKEYBLOB pubkey = null;
        Util.blue("============SKF_TOOL getPubkey ...==================");
        try{
            LongByReference lbr_pulBlobLen = new LongByReference();
            ret = ukey.SKF_ExportPublicKey(p_hcont, false, null, lbr_pulBlobLen);
            long l_pulBlobLen = lbr_pulBlobLen.getValue();
            Util.red(ret + " SKF_ExportPublicKey 公钥大小 = [" + l_pulBlobLen + "]");

            //PointerByReference xxx[] = new PointerByReference[128];
            //PointerByReference xxx[] = new PointerByReference[(int)l_pulBlobLen];
            pubkey = new Struct_ECCPUBLICKEYBLOB();
            lbr_pulBlobLen.setValue(l_pulBlobLen);
            ret = ukey.SKF_ExportPublicKey(p_hcont, false, pubkey, lbr_pulBlobLen);
            Util.red(ret + " SKF_ExportPublicKey 公钥 bitlen= " + pubkey.get_BitLen());
            Util.red(ret + " SKF_ExportPublicKey 公钥x = [" + Util.bytesToHex(pubkey.XCoordinate) + "]");
            Util.red(ret + " SKF_ExportPublicKey 公钥y = [" + Util.bytesToHex(pubkey.YCoordinate) + "]");
        }catch (Exception exp){
            exp.printStackTrace();
        }
        Util.blue("============SKF_TOOL getPubkey end.==================");
        return pubkey;
    }
    public  String get_cert() {
        int ret ;
        String cert_p7 = "";

        try{
            LongByReference lbr_pulSize = new LongByReference();
            ret = ukey.SKF_EnumContainer(p_happ, null,lbr_pulSize);
            long pulSize = lbr_pulSize.getValue();
            Util.blue(ret + " SKF_EnumContainer 容器名大小 = [" + pulSize + "]");

            Struct_CONTAINER containers= new Struct_CONTAINER();
            ret = ukey.SKF_EnumContainer(p_happ, containers,lbr_pulSize);
            String cont_name = containers.getPointer().getString(0);
            Util.blue(ret + " SKF_EnumContainer 容器名 = [" + cont_name + "]");

            PointerByReference pbr_phContainer = new PointerByReference();
            ret = ukey.SKF_OpenContainer(p_happ, cont_name,pbr_phContainer);
            p_hcont = pbr_phContainer.getValue();
            Util.blue(ret + " SKF_OpenContainer 容器p_hcont = [" + p_hcont + "]");

            LongByReference lbr_pulCertLen = new LongByReference();
            ret = ukey.SKF_ExportCertificate(p_hcont, false, null, lbr_pulCertLen);
            int l_pulCertLen = (int)lbr_pulCertLen.getValue();
            Util.red(ret + " SKF_ExportCertificate 证书长度xx = [" + l_pulCertLen + "]");

            Struct_ECCCERTBLOB pbr_pbCert = new Struct_ECCCERTBLOB.ByReference();
            // TRUE表示签名证书,FALSE表示加密证书
            ret = ukey.SKF_ExportCertificate(p_hcont, false, pbr_pbCert,lbr_pulCertLen);
            cert_p7 = pbr_pbCert.get_cert();
            Util.blue(ret + " SKF_ExportCertificate 证书? = [" + cert_p7 + "]");

        }catch (Exception exp){
            exp.printStackTrace();
        }

        return cert_p7;
    }


    public String sign_p1( String text_plain,String USER_PIN) {
        return sign_p1( text_plain,"utf-8",USER_PIN);
    }
    public String sign_p1( String text_plain,String charsetName,String USER_PIN) {
        int ret ;
        String sign_p1 = "";
        int alg_hash = 1;
        Util.blue("============SKF_TOOL Sign P1...==================");

        try{
            Struct_SM3BLOB pbr_pbHashData =sm3_with_userid_ex(text_plain, "utf-8");

            Struct_ECCSIGNATUREBLOB pbr_sign = new Struct_ECCSIGNATUREBLOB();
            ret = ukey.SKF_ECCSignData(p_hcont,pbr_pbHashData,32 ,pbr_sign);
            //Util.blue(ret + " SKF_ECCSignData p1签名长度 = [" + lbr_pulSigLen.getValue() + "]");
            sign_p1 = pbr_sign.get_sign();
            Util.blue(ret + " SKF_ECCSignData p1签名 = [" + sign_p1 + "]");
        }catch (Exception exp){
            exp.printStackTrace();
        }
        Util.blue("============SKF_TOOL Sign P1 end.==================\r\n");
        return sign_p1;
    }

    public  int verify_p1( String text_plain,String sign_p1) {
        return verify_p1(text_plain,"utf-8", sign_p1);
    }
    public  int verify_p1( String text_plain,String charsetName,String sign_p1) {
        int ret = -1;
        int ret_verify = -1;
        //String sign_p1 = "";
        int alg_hash = 1;
        Util.blue("============SKF_TOOL Verify P1 ...==================");

        try{
            Struct_SM3BLOB pbr_pbHashData =sm3_with_userid_ex(text_plain, "utf-8");

            Struct_ECCSIGNATUREBLOB pbr_sign = new Struct_ECCSIGNATUREBLOB();
            pbr_sign.parse_from_p1(sign_p1);

            Struct_ECCPUBLICKEYBLOB pubkey = get_pubkey();

            //SKF_ECCVerify(Pointer hDev, Struct_ECCPUBLICKEYBLOB pbData, int ulDataLen, Struct_ECCSIGNATUREBLOB pSignature);
            ret = ukey.SKF_ECCVerify(p_hdev, pubkey,  pbr_pbHashData,32,pbr_sign);
            Util.blue(ret + " SKF_ECCVerify 验证签名 = [" + ret + "]");
            ret_verify = ret;
        }catch (Exception exp){
            exp.printStackTrace();
        }
        Util.blue("============SKF_TOOL Verify P1 end.==================");
        return ret_verify;
    }
}

package com.terry.skf.tool;

import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;

/**
 * Created by Administrator on 2021/11/30 0030.
 */
public class Util {
    public static boolean flag_debug = false;
    /**
     * 字节数组转16进制
     * @param bytes 需要转换的byte数组
     * @return  转换后的Hex字符串
     */
    public static String bytesToHex(byte[] bytes) {
        StringBuffer sb = new StringBuffer();
        for(int i = 0; i < bytes.length; i++) {
            String hex = Integer.toHexString(bytes[i] & 0xFF);
            if(hex.length() < 2){
                sb.append(0);
            }
            sb.append(hex);
        }
        return sb.toString();
    }

    // 使用ArrayList方法
//java 合并两个byte数组
//    https://www.cnblogs.com/wisdo/p/5074434.html
    //System.arraycopy()方法
    public static byte[] byteMerger(byte[] bt1, byte[] bt2){
        byte[] bt3 = new byte[bt1.length+bt2.length];
        System.arraycopy(bt1, 0, bt3, 0, bt1.length);
        System.arraycopy(bt2, 0, bt3, bt1.length, bt2.length);
        return bt3;
    }


    public static void debug(boolean flag) {
        //System.out.println("我是一条log");
        /* 日志字体颜色 */
        flag_debug = flag;
    }

    public static void red(String args) {
        //System.out.println("我是一条log");
        /* 日志字体颜色 */
        if(flag_debug)
            System.out.println(Util.RED+args+Util.RESET);
    }
    public static void redxx(String args) {
        //System.out.println("我是一条log");
        /* 日志字体颜色 */
        if(flag_debug)
            System.out.print(Util.RED+args+Util.RESET);
    }

    public static void blue(String args) {
        //System.out.println("我是一条log");
        /* 日志字体颜色 */
        if(flag_debug)
            System.out.println(Util.BLUE+args+Util.RESET);
    }
    public static String getString(ByteBuffer buffer)
    {
        Charset charset = null;
        CharsetDecoder decoder = null;
        CharBuffer charBuffer = null;
        try
        {
            charset = Charset.forName("UTF-8");
            decoder = charset.newDecoder();
            // charBuffer = decoder.decode(buffer);//用这个的话,只能输出来一次结果,第二次显示为空
            charBuffer = decoder.decode(buffer.asReadOnlyBuffer());
            return charBuffer.toString();
        }
        catch (Exception ex)
        {
            ex.printStackTrace();
            return "";
        }
    }

    // Reset
    public static final String RESET = "\033[0m";  // Text Reset

    // Regular Colors
    public static final String WHITE = "\033[0;30m";   // WHITE
    public static final String RED = "\033[0;31m";     // RED
    public static final String GREEN = "\033[0;32m";   // GREEN
    public static final String YELLOW = "\033[0;33m";  // YELLOW
    public static final String BLUE = "\033[0;34m";    // BLUE
    public static final String PURPLE = "\033[0;35m";  // PURPLE
    public static final String CYAN = "\033[0;36m";    // CYAN
    public static final String GREY = "\033[0;37m";   // GREY

    // Bold
    public static final String WHITE_BOLD = "\033[1;30m";  // WHITE
    public static final String RED_BOLD = "\033[1;31m";    // RED
    public static final String GREEN_BOLD = "\033[1;32m";  // GREEN
    public static final String YELLOW_BOLD = "\033[1;33m"; // YELLOW
    public static final String BLUE_BOLD = "\033[1;34m";   // BLUE
    public static final String PURPLE_BOLD = "\033[1;35m"; // PURPLE
    public static final String CYAN_BOLD = "\033[1;36m";   // CYAN
    public static final String GREY_BOLD = "\033[1;37m";  // GREY

    // Underline
    public static final String WHITE_UNDERLINED = "\033[4;30m";  // WHITE
    public static final String RED_UNDERLINED = "\033[4;31m";    // RED
    public static final String GREEN_UNDERLINED = "\033[4;32m";  // GREEN
    public static final String YELLOW_UNDERLINED = "\033[4;33m"; // YELLOW
    public static final String BLUE_UNDERLINED = "\033[4;34m";   // BLUE
    public static final String PURPLE_UNDERLINED = "\033[4;35m"; // PURPLE
    public static final String CYAN_UNDERLINED = "\033[4;36m";   // CYAN
    public static final String GREY_UNDERLINED = "\033[4;37m";  // GREY

    // Background
    public static final String WHITE_BACKGROUND = "\033[40m";  // WHITE
    public static final String RED_BACKGROUND = "\033[41m";    // RED
    public static final String GREEN_BACKGROUND = "\033[42m";  // GREEN
    public static final String YELLOW_BACKGROUND = "\033[43m"; // YELLOW
    public static final String BLUE_BACKGROUND = "\033[44m";   // BLUE
    public static final String PURPLE_BACKGROUND = "\033[45m"; // PURPLE
    public static final String CYAN_BACKGROUND = "\033[46m";   // CYAN
    public static final String GREY_BACKGROUND = "\033[47m";  // GREY

    // High Intensity
    public static final String WHITE_BRIGHT = "\033[0;90m";  // WHITE
    public static final String RED_BRIGHT = "\033[0;91m";    // RED
    public static final String GREEN_BRIGHT = "\033[0;92m";  // GREEN
    public static final String YELLOW_BRIGHT = "\033[0;93m"; // YELLOW
    public static final String BLUE_BRIGHT = "\033[0;94m";   // BLUE
    public static final String PURPLE_BRIGHT = "\033[0;95m"; // PURPLE
    public static final String CYAN_BRIGHT = "\033[0;96m";   // CYAN
    public static final String GREY_BRIGHT = "\033[0;97m";  // GREY

    // Bold High Intensity
    public static final String WHITE_BOLD_BRIGHT = "\033[1;90m"; // WHITE
    public static final String RED_BOLD_BRIGHT = "\033[1;91m";   // RED
    public static final String GREEN_BOLD_BRIGHT = "\033[1;92m"; // GREEN
    public static final String YELLOW_BOLD_BRIGHT = "\033[1;93m";// YELLOW
    public static final String BLUE_BOLD_BRIGHT = "\033[1;94m";  // BLUE
    public static final String PURPLE_BOLD_BRIGHT = "\033[1;95m";// PURPLE
    public static final String CYAN_BOLD_BRIGHT = "\033[1;96m";  // CYAN
    public static final String GREY_BOLD_BRIGHT = "\033[1;97m"; // GREY

    // High Intensity backgrounds
    public static final String WHITE_BACKGROUND_BRIGHT = "\033[0;100m";// WHITE
    public static final String RED_BACKGROUND_BRIGHT = "\033[0;101m";// RED
    public static final String GREEN_BACKGROUND_BRIGHT = "\033[0;102m";// GREEN
    public static final String YELLOW_BACKGROUND_BRIGHT = "\033[0;103m";// YELLOW
    public static final String BLUE_BACKGROUND_BRIGHT = "\033[0;104m";// BLUE
    public static final String PURPLE_BACKGROUND_BRIGHT = "\033[0;105m"; // PURPLE
    public static final String CYAN_BACKGROUND_BRIGHT = "\033[0;106m";  // CYAN
    public static final String GREY_BACKGROUND_BRIGHT = "\033[0;107m";   // GREY

    public static void main(String[] args) {
        String str = new String();
        for (int i = 0; i < args.length; i++) {
            System.out.println(args[i]);
            str += args[i];
        }
        System.out.println(str);
    }
}
package com.terry.skf.struct;

import com.sun.jna.Structure;

import java.util.Arrays;
import java.util.List;

// https://www.cnblogs.com/gmhappy/p/11864037.html

public  class Struct_ECCPUBLICKEYBLOB extends Structure{
    /*
  typedef struct Struct_ECCPUBLICKEYBLOB{
  ULONG	BitLen;
  BYTE	XCoordinate[ECC_MAX_XCOORDINATE_BITS_LEN/8];
  BYTE	YCoordinate[ECC_MAX_YCOORDINATE_BITS_LEN/8];
  }ECCPUBLICKEYBLOB, *PECCPUBLICKEYBLOB;
  */
    public Long BitLen;
    public byte[] XCoordinate = new byte[64];
    public byte[] YCoordinate = new byte[64];

    public static class ByReference extends Struct_ECCPUBLICKEYBLOB implements Structure.ByReference {}
    public static class ByValue extends Struct_ECCPUBLICKEYBLOB implements Structure.ByValue {}
    public Long get_BitLen() {
        return BitLen;
    }

    @Override
    protected List getFieldOrder() {
        return Arrays.asList(new String[]{"BitLen", "XCoordinate", "YCoordinate"});
    }



}
    //public void sayUser(Struct_ECCPUBLICKEYBLOB.ByReference struct);

其他struct结构都类似这个结构。

测试代码:

package test;

// https://www.jianshu.com/p/dceae90f8537
// 功能测试列表:
// 1. 计算 SM3 Hash (无需公钥)
// 2. 计算 SM3 Hash   (需要公钥,默认userid=1234567812345678)
// 3. 计算pkcs1 签名 (使用SM3 Hash带公钥算法)
// 4. pkcs1验证签名
// 20211203: 存在问题,原文不能包含中文,否则SM3 Hash,签名结果与xtx不兼容。
import com.terry.skf.SKF_TOOL;
import com.terry.skf.tool.Util;

public class skf_test_demo {

    public static void main(String[] args) {
        String text_plain = "123测试原文";       // 问题:汉字原文做sm3后的结果,与xtx控件做sm3的结果,不一致!
        text_plain = "123test1";
        System.out.println("text_plain = " + text_plain);

        String USER_PIN = "111111";
        Util.debug(false);

        SKF_TOOL skf = new SKF_TOOL(USER_PIN);

        String[] charsetname = {"Unicode","utf-16","utf-8","gbk","gb2312","GB18030","ASCII","ISO-8859-1"};
        for( int i =0;i<charsetname.length;i++){
            String sm3_no_userid = skf.sm3_no_userid(text_plain, charsetname[i]);
            System.out.println("sm3_no_userid = " + sm3_no_userid + " " + charsetname[i]);
        }

        String sm3_no_userid = skf.sm3_no_userid(text_plain);
        System.out.println("sm3_no_userid = " + sm3_no_userid );

        String sm3_with_userid = skf.sm3_with_userid(text_plain);
        System.out.println("sm3_with_userid = " + sm3_with_userid);

        //String cert = get_cert();
       // System.out.println("cert = " + cert);

        String sign_p1 = skf.sign_p1(text_plain, USER_PIN);
        System.out.println("sign_p1 = " + sign_p1);

        long startTime=System.currentTimeMillis();   //获取开始时间
        for(int i=0;i<51;i++) {
            sign_p1 = skf.sign_p1(text_plain, USER_PIN);
            System.out.println(i + " sign_p1 = " + sign_p1);
        }
        long endTime=System.currentTimeMillis(); //获取结束时间
        System.out.println("程序运行时间: "+(endTime-startTime)+"ms");

        //text_plain = "123test1篡改了";
        //sign_p1 = "MEUCIFQbP1fYfIeQZlYqb8q4qQ0FWPvMS+3zXy50jDC3vpEmAiEAqf4G/Aq2xw6MVsMHP4HsrP7K0PJSedGOdh8qlDPRxv8=";
        int verify_p1 = skf.verify_p1( text_plain, sign_p1);
        System.out.println("verify_p1 = " + verify_p1);

        // 释放ukey资源
        skf.close();
    }
}

20220308: 补充几个struct结构

package com.terry.skf.struct;

import com.sun.jna.Structure;

import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * Created by Administrator on 2021/12/1 0001.
 */
public class Struct_CONTAINER extends Structure{
    public byte[] container = new byte[128];
    public static class ByReference extends Struct_CONTAINER implements Structure.ByReference {}
    public static class ByValue extends Struct_CONTAINER implements Structure.ByValue {}
    public byte[]  get_container() {
        return container;
    }
    public List<String>  get_containers() {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        List<String> ls = new ArrayList<String>();
        int j = 0;
        for(int i=0;i<container.length;i++){
            baos.write(container[i]);
            if(container[i] == 0){
                //System.out.println(i + " cont[i] = 00" + container[i]);
                String temp = new String(baos.toByteArray()).trim();
                if(temp.length() > 0){
                    ls.add(temp);
                    //System.out.println(j + " temp = " + temp);
                    j = j+1;
                    baos.reset();
                }
                //break;
            }
        }
        return ls;
    }

    @Override
    protected List getFieldOrder() {
        return Arrays.asList(new String[]{"container"});
    }
}
package com.terry.skf.struct;

import com.sun.jna.Structure;

import java.util.Arrays;
import java.util.Base64;
import java.util.List;

// https://www.cnblogs.com/gmhappy/p/11864037.html

public  class Struct_ECCCERTBLOB extends Structure{
    public byte[] cert = new byte[735];
    public static class ByReference extends Struct_ECCCERTBLOB implements Structure.ByReference {}
    public static class ByValue extends Struct_ECCCERTBLOB implements Structure.ByValue {}
    public String  get_cert() {
        String cert_b64 = Base64.getEncoder().encodeToString(cert);
        return cert_b64;
    }

    @Override
    protected List getFieldOrder() {
        return Arrays.asList(new String[]{"cert"});
    }
}
    //public void sayUser(Struct_ECCPUBLICKEYBLOB.ByReference struct);
package com.terry.skf.struct;

import com.sun.jna.Structure;

import java.util.Arrays;
import java.util.List;

// https://www.cnblogs.com/gmhappy/p/11864037.html

public  class Struct_ECCPUBLICKEYBLOB extends Structure{
    /*
  typedef struct Struct_ECCPUBLICKEYBLOB{
  ULONG	BitLen;
  BYTE	XCoordinate[ECC_MAX_XCOORDINATE_BITS_LEN/8];
  BYTE	YCoordinate[ECC_MAX_YCOORDINATE_BITS_LEN/8];
  }ECCPUBLICKEYBLOB, *PECCPUBLICKEYBLOB;
  */
    public Long BitLen;
    public byte[] XCoordinate = new byte[64];
    public byte[] YCoordinate = new byte[64];

    public static class ByReference extends Struct_ECCPUBLICKEYBLOB implements Structure.ByReference {}
    public static class ByValue extends Struct_ECCPUBLICKEYBLOB implements Structure.ByValue {}
    public Long get_BitLen() {
        return BitLen;
    }

    @Override
    protected List getFieldOrder() {
        return Arrays.asList(new String[]{"BitLen", "XCoordinate", "YCoordinate"});
    }



}
    //public void sayUser(Struct_ECCPUBLICKEYBLOB.ByReference struct);
package com.terry.skf.struct;

import com.sun.jna.Structure;
import com.terry.skf.tool.Util;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.Base64;
import java.util.List;

// https://www.cnblogs.com/gmhappy/p/11864037.html

public  class Struct_ECCSIGNATUREBLOB extends Structure{
  // ECC签名数据结构
  /*
  typedef struct Struct_ECCSIGNATUREBLOB{
    BYTE	r[ECC_MAX_XCOORDINATE_BITS_LEN/8];
    BYTE	s[ECC_MAX_YCOORDINATE_BITS_LEN/8];
  } ECCSIGNATUREBLOB, *PECCSIGNATUREBLOB;
*/
    public byte[] rb = new byte[32];
    public byte[] r = new byte[32];
    public byte[] sb = new byte[32];
    public byte[] s = new byte[32];
    public static class ByReference extends Struct_ECCSIGNATUREBLOB implements Structure.ByReference {}
    public static class ByValue extends Struct_ECCSIGNATUREBLOB implements Structure.ByValue {}
  public byte[] get_r() {
        return r;
    }
  public byte[] get_s() {
      return s;
    }

  // https://blog.csdn.net/daihuimaozideren/article/details/81072738
    // 30 + LEN1 + 02 + LEN2 + 00 (optional) + r + 02 + LEN3 + 00(optional) + s
    // 当r或s的第1字节大于0x80时,需要在r或s前加1字节0x00。
  public String get_sign() {
      ByteArrayOutputStream baos = new ByteArrayOutputStream();
      byte[] h ={48,68};

      byte[] r_h = {02,32};
      byte[] s_h = {02,32};
      byte[] r_h2 = {02,33,00};
      byte[] s_h2 = {02,33,00};
      boolean flag_r = false;
      boolean flag_s = false;

      String sign_b64 = "";

      if(r[0] < 0){
        Util.red("r0 < 0 = " + r[0]);
        flag_r = true;
        h[1] = 69 ; //{48,69};
      }
      if(s[0] < 0){
        Util.red("s0 < 0 = " + s[0]);
        flag_s = true;
        h[1] =69 ; //{48,69};
      }
      if((r[0] < 0) && (s[0] < 0)){
        h[1] = 70 ; //{48,69};
      }

      try {
        baos.write(h);

        if(flag_r){
          byte[] r_temp = Util.byteMerger(r_h2, r);
          baos.write(r_temp);
        }else{
          byte[] r_temp = Util.byteMerger(r_h, r);
          baos.write(r_temp);
        }

        if(flag_s){
          byte[] s_temp = Util.byteMerger(s_h2, s);
          baos.write(s_temp);
        }else{
          byte[] s_temp = Util.byteMerger(s_h, s);
          baos.write(s_temp);
        }

      } catch (IOException e) {
        e.printStackTrace();
      }

      //byte[] r_s_temp = Util.byteMerger(r_temp, s_temp);
      //byte[] sign = Util.byteMerger(h, r_s_temp);
      byte[] sign = baos.toByteArray();
      Util.red("baos = " + Util.bytesToHex(sign)) ;
      sign_b64 = Base64.getEncoder().encodeToString(sign);
      return sign_b64;
    }

  public int parse_from_p1(String sign_p1_base64) {
      if(sign_p1_base64.length() == 0){
        return -1;
      }
      byte[] sign_decoded = Base64.getDecoder().decode(sign_p1_base64);
      Util.red("hex sign_p1 = " + Util.bytesToHex(sign_decoded));

      ByteArrayOutputStream baos = new ByteArrayOutputStream();
      byte[] r_temp = new byte[32];
      //r0 < 0 = -93
      //s0 < 0 = -19
      //baos = 3046022100a3402e5a90b05a1f5b559c5c419fd1d4c066f6bc04725ef6804045f3f5e7db32022100ed47788ce825f2b6dea62139e9c6f9adb91c71e0358e5e60b55768e9fbc20aa2

      //int len_rs =  sign_decoded[1];
      //System.out.println("len_rs = " +  len_rs);

      int leng_r = sign_decoded[3];
      Util.red("leng_r = " + leng_r);

      // 30 leng_r+leng_s | 02 leng_r(x00 _32_) | 02 leng_s( x00 _32_)
      int leng_s = sign_decoded[2 + 1 + leng_r + 2];
      Util.red("leng_s = " + leng_s);

      for(int i =0; i< 32; i++){
        if(leng_r == 32){
          baos.write(sign_decoded[4 + i]);
        }
        if(leng_r == 33){
          baos.write(sign_decoded[5 + i]);
        }
      }
      r = baos.toByteArray();
      //System.out.println("hex r = " +  Util.bytesToHex(r));
      Util.red("hex r = " + Util.bytesToHex(r)) ;
      baos.reset();

      int index_s = sign_decoded.length -32;
      for(int i =0; i< 32; i++){
          baos.write(sign_decoded[index_s + i]);
      }
      s = baos.toByteArray();
      //System.out.println("hex s = " +  Util.bytesToHex(s));
      Util.red("hex s = " + Util.bytesToHex(s)) ;
      baos.reset();

    return 1;
  }

  @Override
    protected List getFieldOrder() {
        return Arrays.asList(new String[]{"rb", "r", "sb", "s"});
    }



}
    //public void sayUser(Struct_ECCPUBLICKEYBLOB.ByReference struct);
package com.terry.skf.struct;

import com.sun.jna.Structure;

import java.util.Arrays;
import java.util.List;

// https://www.cnblogs.com/gmhappy/p/11864037.html

public  class Struct_RSAPUBLICKEYBLOB extends Structure{
    /*
 //RSA公钥交换数据块
typedef struct Struct_RSAPUBLICKEYBLOB{
	ULONG	AlgID;									//算法标识号
	ULONG	BitLen;									//模数的实际位长度,必须是8的倍数
	BYTE	Modulus[MAX_RSA_MODULUS_LEN];			//模数n=p*q,实际长度为BitLen/8字节
	BYTE	PublicExponent[MAX_RSA_EXPONENT_LEN];	//公开密钥e, 一般为00010001
} RSAPUBLICKEYBLOB, *PRSAPUBLICKEYBLOB;
  */
    public Long AlgID;
    public Long BitLen;
    public byte[] Modulus = new byte[256];
    public byte[] PublicExponent = new byte[4];

    public static class ByReference extends Struct_RSAPUBLICKEYBLOB implements Structure.ByReference {}
    public static class ByValue extends Struct_RSAPUBLICKEYBLOB implements Structure.ByValue {}
    public Long get_AlgID() {
        return AlgID;
    }
    public Long get_BitLen() {
      return BitLen;
    }
    @Override
    protected List getFieldOrder() {
        return Arrays.asList(new String[]{"AlgID","BitLen", "Modulus", "PublicExponent"});
    }



}
    //public void sayUser(Struct_ECCPUBLICKEYBLOB.ByReference struct);
package com.terry.skf.struct;

import com.sun.jna.Structure;

import java.util.Arrays;
import java.util.Base64;
import java.util.List;

// https://www.cnblogs.com/gmhappy/p/11864037.html

public  class Struct_SM3BLOB extends Structure{
    public byte[] sm3 = new byte[32];
    public static class ByReference extends Struct_SM3BLOB implements Structure.ByReference {}
    public static class ByValue extends Struct_SM3BLOB implements Structure.ByValue {}
    public byte[]  get_sm3() {
        return sm3;
    }
    public String  get_sm3_b64() {
        String sm3_b64 = Base64.getEncoder().encodeToString(sm3);
        return sm3_b64;
    }
    @Override
    protected List getFieldOrder() {
        return Arrays.asList(new String[]{"sm3"});
    }
}
    //public void sayUser(Struct_ECCPUBLICKEYBLOB.ByReference struct);

  • 4
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 25
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 25
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值