SKF toolkit UKEY encryption and decryption JAVA interface calls UKEY DLL/SO driver

Recently, the company needs to develop national encryption and decryption based on the UKEY method. After searching around the Internet, I can only find the only UEKY interface of Longmai Technology, and there are only a few. After a period of exploration, I finally finished writing the test and passed it. (Ukey provided by Haitai Fangyuan manufacturer is used. No matter which manufacturer it is, it is developed in accordance with the interface specifications required by the GJ Cryptozoology Bureau. It can be used as a reference)

Implemented SM4 encryption and decryption and SM2 encryption and decryption and unblocked all JAVA interfaces provided by UKEY. If you need the source code, please contact v lalawangzi1986 for paid guidance.

Post the source code of the test process:


import com.sun.jna.*;
import com.sun.jna.ptr.ByteByReference;
import com.sun.jna.ptr.IntByReference;
import com.sun.jna.ptr.LongByReference;
import com.sun.jna.ptr.PointerByReference;

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

public class SKFUtil5 {

    public interface CLibrary extends Library {
        CLibrary INSTANCE = (CLibrary)
                Native.loadLibrary((Platform.isWindows() ? "C:\\Windows\\SysWOW64\SKFAPI30987.dll" : "/opt/data/workdir/libSKFAPI-arm64.so\ "),
                        CLibrary.class);

        //Device operation
        long SKF_EnumDev(boolean bPresent, ByteByReference szNameList, LongByReference pulSize);
        long SKF_ConnectDev(String szName, PointerByReference phDev);
        long SKF_DisConnectDev(Pointer hDev);
        long SKF_GetDevInfo(Pointer hDev, DEVINFO pDevInfo);

        //Application operation
        int SKF_EnumApplication(Pointer hDev, ByteByReference szAppName, LongByReference pulSize);
        int SKF_CreateApplication(Pointer hDev, String szAppName, String szAdminPin
                ,int dwAdminPinRetryCount, String szUserPin, int dwUserPinRetryCount,
                int dwCreateFileRights, PointerByReference happ);
        int SKF_OpenApplication(Pointer hDev, String pappname, PointerByReference happ);
        int SKF_CloseApplication(Pointer hDev);

        //Access control
        int SKF_ChangeDevAuthKey(Pointer hDev, byte[] pbKeyValue, int ulKeyLen);
        int SKF_DevAuth(Pointer hDev, byte[] pbAuthData, int ulLen);
        int SKF_ChangePIN(Pointer hApplication, int ulPINType, String oldPIN,String newPIN, IntByReference pulRetryCount);
        int SKF_GetPINInfo(Pointer hApplication, int ulPINType, IntByReference pulMaxRetryCount, IntByReference pulRemainRetryCount, IntByReference pbDefaultPin);
        int SKF_VerifyPIN(Pointer hApplication, int ulPINType, String szPIN, LongByReference pulRetryCount);
        int SKF_UnblockPIN(Pointer hApplication, String szAdminPIN, String szNewUserPIN, IntByReference pulRetryCount);
        int SKF_ClearSecueState(Pointer hApplication);

        //container management
        int SKF_CreateContainer(Pointer hApplication, String szContainerName,PointerByReference phContainer);
        int SKF_DeleteContainer(Pointer hApplication, String szContainerName);
        int SKF_EnumContainer(Pointer hApplication, byte[] szContainerName, IntByReference pulSize);
        int SKF_OpenContainer(Pointer hApplication,String szContainerName,PointerByReference phContainer);
        int SKF_CloseContainer(Pointer hContainer);
        int SKF_GetContainerType(Pointer hContainer, LongByReference pulContainerType);
        int SKF_ExportCertificate(Pointer hContainer, boolean bSignFlag, byte[] pbCert, IntByReference pulCertLen);
        int SKF_ImportCertificate(Pointer hContainer, boolean bSignFlag, byte[] pbCert, IntByReference pulCertLen);

        //Password service
        //encryption
        int SKF_EncryptInit(Pointer hKey, BLOCKCIPHERPARAM.ByValue EncryptParam);
        int SKF_Encrypt(Pointer hKey, byte[] pbData, int ulDataLen, byte[] pbEncryptedData, IntByReference pulEncryptedLen);
        int SKF_EncryptUpdate(Pointer hKey, byte[] pbData, int ulDataLen,byte[] pbEncryptedData, IntByReference pulEncryptedLen);
        int SKF_EncryptFinal(Pointer hKey, byte[] pbEncryptedData, IntByReference ulEncryptedDataLen);
        //Decrypt
        int SKF_DecryptInit(Pointer hKey, BLOCKCIPHERPARAM.ByValue DecryptParam);
        int SKF_Decrypt(Pointer hKey, byte[] pbEncryptedData, int ulEncryptedLen, byte[] pbData, IntByReference pulDataLen);
        int SKF_DecryptFinal(Pointer hKey, byte[] pbDecryptedData, IntByReference pulDecryptedDataLen);
        //Export import
        //bSignFlag=TRUE means to export the signature public key, FALSE means to export the encryption public key
        int SKF_ExportPublicKey(Pointer hContainer, boolean bSignFlag, byte[] pbBlob, IntByReference pulBlobLen);

        int SKF_GenECCKeyPair(Pointer hContainer, NativeLong ulAlgId, ECCPUBLICKEYBLOB pBlob);
        int SKF_DigestInit(Pointer hDev, int ulAlgID, ECCPUBLICKEYBLOB pPubKey, byte[] pucID, int ulIDLen, PointerByReference phHash);
        int SKF_Digest(Pointer hHash, byte[] pbData, int ulDataLen, byte[] pbHashData, IntByReference pulHashLen);
        int SKF_DigestUpdate(Pointer hHash, byte[] pbData, int ulDataLen);
        int SKF_DigestFinal(Pointer hHash, byte[] pHashData, IntByReference pulHashLen);
        int SKF_ECCSignData(Pointer hContainer, byte[] pbData, int ulDataLen, ECCSIGNATUREBLOB pSignature);
        int SKF_ECCVerify(Pointer hDev, ECCPUBLICKEYBLOB pECCPubKeyBlob, byte[] pbData, int ulDataLen, ECCSIGNATUREBLOB pSignature);
        int SKF_ECCExportSessionKey(Pointer hContainer, int ulAlgId, ECCPUBLICKEYBLOB pPubKey, ECCCIPHERBLOB pData, PointerByReference phSessionKey);
        int SKF_ImportECCKeyPair(Pointer hContainer, ENVELOPEDKEYBLOB pEnvelopedKeyBlob);
        int SKF_ExtECCSign(Pointer hDev, ECCPRIVATEKEYBLOB pECCPriKeyBlob, byte[] pbData, int ulDataLen, ECCSIGNATUREBLOB pSignature);
        int SKF_ExtECCVerify(Pointer hDev,ECCPUBLICKEYBLOB pECCPubKeyBlob, byte[] pbData, int ulDataLen, ECCSIGNATUREBLOB pSignature);
        int SKF_ExtECCEncrypt(Pointer hDev, ECCPUBLICKEYBLOB pECCPubKeyBlob, byte[] pbPlainText, int ulPlainTextLen, ECCCIPHERBLOB pCipherText);
        int SKF_ExtECCDecrypt(Pointer hDev, ECCPRIVATEKEYBLOB pECCPriKeyBlob, ECCCIPHERBLOB pCipherText, byte[] pbPlainText, IntByReference pulPlainTextLen);

        //Other operations
        int SKF_SetSymmKey(Pointer hDev, byte[] pbKey, int ulAlgID, PointerByReference phKey);
        int SKF_SetSymmKey(Pointer hDev, byte[] pbKey, NativeLong ulAlgID, PointerByReference phKey);

        public static class VERSION extends Structure {
            public int major;
            public int minor;
            public static class ByReference extends VERSION implements Structure.ByReference {}
            public static class ByValue extends VERSION implements Structure.ByValue {}
            @Override
            protected List<String> getFieldOrder() {
                return Arrays.asList(new String[] { "major", "minor"});
            }
        }

        public static class DEVINFO extends Structure {
            public VERSION Version;
            public byte[] Manufacturer = new byte[64];
            public byte[] Issuer = new byte[64];
            public byte[] Label = new byte[32];
            public byte[] SerialNumber = new byte[32];
            public VERSION HWVersion;
            public VERSION FirmwareVersion;
            public int AlgSymCap;
            public int AlgAsymCap;
            public int AlgHashCap;
            public int DevAuthAlgId;
            public int TotalSpace;
            public int FreeSpace;
            public byte[] Reserved = new byte[64];
            public static class ByReference extends DEVINFO implements Structure.ByReference {}
            public static class ByValue extends DEVINFO implements Structure.ByValue {}
            @Override
            protected List<String> getFieldOrder() {
                return Arrays.asList(new String[] { "Version", "Manufacturer", "Issuer", "Label", "SerialNumber"
                        , "HWVersion", "FirmwareVersion", "AlgSymCap", "AlgAsymCap", "AlgHashCap", "DevAuthAlgId"
                        , "TotalSpace", "FreeSpace", "Reserved"});
            }
        }

        public static class BLOCKCIPHERPARAM extends Structure {
            public byte[] IVS = new byte[32];
            public intIVLen = 0;
            public int PaddingType = 0;
            public int FeedBitLen = 0;

            @Override
            protected List<String> getFieldOrder() {
                return Arrays.asList(new String[] { "IVS", "IVLen", "PaddingType", "FeedBitLen"});
            }

            public static class ByReference extends BLOCKCIPHERPARAM implements Structure.ByReference {}
            public static class ByValue extends BLOCKCIPHERPARAM implements Structure.ByValue {}

        }
        public static class ECCPUBLICKEYBLOB extends Structure {
            public static final int ECC_MAX_XCOORDINATE_BITS_LEN = 512;
            public static final int ECC_MAX_YCOORDINATE_BITS_LEN = 512;
            public int BitLen;
            public byte[] XCoordinate = new byte[ECC_MAX_XCOORDINATE_BITS_LEN/8];
            public byte[] YCoordinate = new byte[ECC_MAX_YCOORDINATE_BITS_LEN/8];

            @Override
            protected List<String> getFieldOrder() {
                return Arrays.asList(new String[] { "BitLen", "XCoordinate", "YCoordinate"});
            }
// public static class ByReference extends ECCPUBLICKEYBLOB implements Structure.ByReference { }
            public static class ByValue extends ECCPUBLICKEYBLOB implements Structure.ByValue {}
        }

        public static class ECCPRIVATEKEYBLOB extends Structure {
            public static final int ECC_MAX_MODULUS_BITS_LEN = 512;
            public int BitLen;
            public byte[] PrivateKey = new byte[ECC_MAX_MODULUS_BITS_LEN/8];
            @Override
            protected List<String> getFieldOrder() {
                return Arrays.asList(new String[] { "BitLen", "PrivateKey"});
            }
            public static class ByReference extends ECCPRIVATEKEYBLOB implements Structure.ByReference { }
            public static class ByValue extends ECCPRIVATEKEYBLOB implements Structure.ByValue {}
        }
        public static class ECCCIPHERBLOB extends Structure {
            public static final int ECC_MAX_XCOORDINATE_BITS_LEN = 512;
            public byte[] XCoordinate = new byte[ECC_MAX_XCOORDINATE_BITS_LEN/8];
            public byte[] YCoordinate = new byte[ECC_MAX_XCOORDINATE_BITS_LEN/8];
            public byte[] HASH = new byte[32];
            public int CipherLen;
            public byte[] Cipher = new byte[1];
            @Override
            protected List<String> getFieldOrder() {
                return Arrays.asList(new String[] { "XCoordinate", "YCoordinate", "HASH", "CipherLen", "Cipher"});
            }
            public static class ByReference extends ECCCIPHERBLOB implements Structure.ByReference { }
            public static class ByValue extends ECCCIPHERBLOB implements Structure.ByValue {}
        }
        public static class ECCSIGNATUREBLOB extends Structure {
            public static final int ECC_MAX_XCOORDINATE_BITS_LEN = 512;
            public byte[] r = new byte[ECC_MAX_XCOORDINATE_BITS_LEN/8];
            public byte[] s = new byte[ECC_MAX_XCOORDINATE_BITS_LEN/8];
            @Override
            protected List<String> getFieldOrder() {
                return Arrays.asList(new String[] { "r", "s"});
            }
            public static class ByReference extends ECCSIGNATUREBLOB implements Structure.ByReference { }
            public static class ByValue extends ECCSIGNATUREBLOB implements Structure.ByValue {}
        }
        public static class ENVELOPEDKEYBLOB extends Structure {
            public int Version;
            public int ulSymmAlgID;
            public int ulBits;
            public byte[] cbEncryptedPriKey = new byte[64];
            public ECCPUBLICKEYBLOB.ByReference PubKey;
            public ECCCIPHERBLOB.ByReference ECCCipherBlob;
            @Override
            protected List<String> getFieldOrder() {
                return Arrays.asList(new String[] { "Version", "ulSymmAlgID", "ulBits", "cbEncryptedPriKey", "PubKey", "ECCCipherBlob"});
            }
            public static class ByReference extends ENVELOPEDKEYBLOB implements Structure.ByReference { }
            public static class ByValue extends ENVELOPEDKEYBLOB implements Structure.ByValue {}
        }
        public static class FILEATTRIBUTE extends Structure {
            public byte[] FileName = new byte[32];
            public int FileSize;
            public int ReadRights;
            public int WriteRights;
            @Override
            protected List<String> getFieldOrder() {
                return Arrays.asList(new String[] { "FileName", "FileSize", "ReadRights", "WriteRights"});
            }
            public static class ByReference extends FILEATTRIBUTE implements Structure.ByReference { }
            public static class ByValue extends FILEATTRIBUTE implements Structure.ByValue {}
        }
    }

    public static void close(CLibrary ukey, Pointer p_hdev){
        long ret = ukey.SKF_DisConnectDev(p_hdev);
        if(ret != 0){
            //throw new Exception("SKF_VerifyPIN fail!");
            System.out.println("SKF_DisConnectDev fail!");
        }
    }

    public static void main(String[] args) throws Exception {
        CLibrary ukey = CLibrary.INSTANCE;

        long ret = -1l;
        ByteByReference deviceNameList = new ByteByReference();
        LongByReference deviceNameListLen = new LongByReference();
        ret = ukey.SKF_EnumDev(true, null, deviceNameListLen);
        long len = deviceNameListLen.getPointer().getLong(0);
        deviceNameListLen.setValue(len);
        ret = ukey.SKF_EnumDev(true, deviceNameList, deviceNameListLen);

        if(ret != 0l){
            System.out.println("USBKey not inserted!");
            return ;
        }

        // Point to the first device
        String deviceName = deviceNameList.getPointer().getString(0);
        PointerByReference hDev = new PointerByReference();
        ret = ukey.SKF_ConnectDev(deviceName, hDev);
        if(ret != 0){
            System.out.println("Failed to connect to device");
            return ;
        }

        Pointer p_hdev = hDev.getValue();
        CLibrary.DEVINFO pDevInfo = new CLibrary.DEVINFO();
        //pDevInfo.clear();

        ret = ukey.SKF_GetDevInfo(p_hdev, pDevInfo);
        if(ret != 0){
            System.out.println("Failed to connect to device");
            return ;
        }
        String s = new String(pDevInfo.Label);

        int APP_NAME_SIZE = 256;


        ByteByReference bbr_applist = new ByteByReference();
        LongByReference lbr_pulSize = new LongByReference();
        //Enumerate all applications present in the device
        ret = ukey.SKF_EnumApplication(p_hdev, bbr_applist, lbr_pulSize);
        len = lbr_pulSize.getPointer().getLong(0);
        bbr_applist = new ByteByReference();
        lbr_pulSize = new LongByReference();
        lbr_pulSize.setValue(len);
        ret = ukey.SKF_EnumApplication(p_hdev, bbr_applist, lbr_pulSize);
        // Fuck!: There is a space at the end of bbr_applist! Needs to be removed!
        String app_name = bbr_applist.getPointer().getString(0).trim();
        PointerByReference pbr_happ = new PointerByReference();

        //Open the specified application
        ret = ukey.SKF_OpenApplication(p_hdev, app_name, pbr_happ);
        Pointer p_happ = pbr_happ.getValue();

        LongByReference lbr_pulRetryCount = new LongByReference();

        ret = ukey.SKF_VerifyPIN(p_happ, 1, "111111", lbr_pulRetryCount);
        if(ret != 0){
            close(ukey, p_hdev);
            throw new Exception("SKF_VerifyPIN fail!");
        }

        //byte[] szContainerName = new byte[1024];
        IntByReference pulSize = new IntByReference();
        ret = ukey.SKF_EnumContainer(p_happ, null, pulSize);
        int len2 = pulSize.getValue();
        pulSize.setValue(len2);

        byte[] szContainerName = new byte[len2];
        ret = ukey.SKF_EnumContainer(p_happ, szContainerName, pulSize);
        String containerNames = new String(szContainerName, 0, pulSize.getValue());
        String [] containerNameList = containerNames.split("\0");

// //Create the specified container DB
        PointerByReference phContainer = new PointerByReference();
        String containerName = "DB";

        ret = ukey.SKF_OpenContainer(p_happ, containerName, phContainer);
        if(ret != 0){
            close(ukey, p_hdev);
            throw new Exception("SKF_OpenContainer fail!");
        }
        Pointer hContainer = phContainer.getValue();

        LongByReference pulContainerType = new LongByReference();
        ret = ukey.SKF_GetContainerType(hContainer, pulContainerType);
        if(ret != 0){
            close(ukey, p_hdev);
            throw new Exception("SKF_GetContainerType fail!");
        }
        System.out.println("pulContainerType=" + pulContainerType.getValue());


        //Next step import SM4 secret key
        String key = "1234567812345678";
        byte[] data = key.getBytes();

        //SGD_SMS4_ECB 0x00000401 SMS4 algorithm ECB encryption mode
        longulAlgID = 0x00000402;
        NativeLong ll = new NativeLong(ulAlgID);
        //int algid=1026;
        int algid=0x00000402;
        PointerByReference phKey = new PointerByReference();

        ret = ukey.SKF_SetSymmKey(p_hdev, data, ll, phKey);
        if(ret != 0){
            close(ukey, p_hdev);
            throw new Exception("SKF_SetSymmKey fail!");
        }

        Pointer hKey = phKey.getValue();


        ret = ukey.SKF_CloseApplication(p_happ);
        if(ret != 0){
            close(ukey, p_hdev);
            throw new Exception("SKF_CloseApplication fail!");
        }
        ret = ukey.SKF_DisConnectDev(p_hdev);
        if(ret != 0){
            //throw new Exception("SKF_VerifyPIN fail!");
            System.out.println("SKF_DisConnectDev fail!");
        }
        p_happ = null;

    }


}

The knowledge points of the article match the official knowledge files, and you can further learn related knowledge. Java Skill TreeHomepageOverview 138767 people are learning the system