美丽的神话 发表于 7 天前

Java调用UK动态库SKF接口(dll/so)——JNA的实现

Java调用UK动态库SKF接口(dll/so)——JNA的实现

   个人对Java语音了解有限,由于工作上的原因,写了一个的demo,仅供参考


   情况:


[*]IntelliJ IDEA Community Edition 2024.1
[*]wiindows10
1-项目搭建

1.1-创建项目

1- 新建项目:选择Maven Archetype
        a- Archetype:任意添加一个,默认第一个(org.apache.maven.archetypes:maven-archetype-archetype)
1.2-JNA依靠

在项目根目录下的pom.xml添加JNA依靠
<dependencies>
    <!-- 添加JNA依赖 -->
    <dependency>
      <groupId>net.java.dev.jna</groupId>
      <artifactId>jna</artifactId>
      <version>5.10.0</version> <!-- 请检查并使用最新版本 -->
    </dependency>
</dependencies>
1.3-目录创建

在src\mian下创建java目录,后续的代码文件将在这个目录下创建完成
2-Java SKFApi接口类的创建

   涉及的内容:


[*]相关数据类型(各结构体):
[*]SKF接口
[*]算法ID
2.1-数据结构的定义

示例:
C的结构体定义:
typedef struct Struct_Version{
   
        BYTE major;
        BYTE minor;
}VERSION;
Java-JNA的对应的定义:
   

[*] getFieldOrder:必须存在的方法,里面的字符串跟结构体变量的顺序保持一致,没有会报错

[*] ByReference和ByValue:非必须的,在结构体类内部再定义两个静态类ByReference和ByValue 用于表示值传递还是引用传递,发起加上。

[*] 可增加其他方法:如果有需要对结构体完成某些操纵,可在后面增加方法,后面的部分结构体的部分中我会增加get和set方法,因为SKF接口中有涉及到将结构体转为byte*类型,或将byte*转为结构体的,以是增加get方法将结构体转为byte数组,set方法将byte数组转为结构体。

public static class VERSION extends Structure {
   
      public int major;
      public int minor;

            // 定义值传递和指针传递类
      public static class ByReference extends VERSION implements Structure.ByReference {
   
            //指针和引用的传递使用ByReference
      }

      public static class ByValue extends VERSION implements Structure.ByValue {
   
            //拷贝参数传递使用ByValue
      }

      @Override
      protected List<String> getFieldOrder() {
   
            return Arrays.asList(new String[]{
   "major", "minor"});
      }
    }
2.2-SKF句柄相关

   SKF涉及到的句柄有:设备句柄、应用句柄、容器句柄、会话密钥句柄、哈希句柄
C中的SKF相关的句柄:
DEVHANDLE *phDev = NULL;                                 // 设备句柄
HAPPLICATION *phApplicatio = NULL;                // 应用句柄
HCONTAINER *phContaine = NULL;                        // 容器句柄
HANDLE *phKeyHandle = NULL;                                // 会话密钥句柄
HANDLE *phHash = NULL;                                        // 哈希句柄

Java-JNA的SKF相关的句柄:
// 句柄的定义
PointerByReference phDev = new PointerByReference();// 设备句柄
PointerByReference phApp = new PointerByReference();// 应用句柄
PointerByReference phContainer = new PointerByReference();// 容器句柄
PointerByReference sessionKey = new PointerByReference();// 会话密钥句柄
PointerByReference pHash = new PointerByReference(); // 哈希句柄

// 在获取句柄的时候传PointerByReference引用,在后续使用句柄的时候用getValue的值,以获取设备句柄,和使用设备句柄接口定义为例:连接设备、断开连接
long SKF_ConnectDev(String szName, PointerByReference phDev); // 连接设备
long SKF_DisConnectDev(Pointer hDev);//断开连接

// 示例
PointerByReference phDev = new PointerByReference();
SKF_ConnectDev(deviceName, phDev)
// 调用SKF_ConnectDev接口后,用getValue方法获取指针
Pointer hDev = phDev.getValue();
SKF_DisConnectDev(hDev)
2.3-注意事项

   

[*]SKF接口中定义为BOOL类型的参数,在Java-JNA中用int类型表示:1表示true,0表示false
   
[*]原因:如果用Java的Boolean类型传,可能会出现传true和false的效果一样   
   
[*]大小端序问题:
   
[*]将数据以byte数组输出大概将byte数据输入(或转为结构体)时要注意此问题,SKF接口是小端序输出的。   

2.4-SKFApi内容

   请根据实际情况加载的动态库:
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.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Arrays;
import java.util.List;


public interface SkfApi extends Library {
   
    SkfApi INSTANCE = Native.load("your_dll_name", SkfApi.class);

    //设备操作
    long SKF_EnumDev(int bPresent, ByteByReference szNameList, IntByReference pulSize);

    long SKF_ConnectDev(String szName, PointerByReference phDev);

    long SKF_DisConnectDev(Pointer hDev);

    long SKF_GetDevInfo(Pointer hDev, DEVINFO pDevInfo);

    //应用操作
    int SKF_EnumApplication(Pointer hDev, ByteByReference szAppName, IntByReference 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 appName, PointerByReference hApp);

    int SKF_CloseApplication(Pointer hApp);

    //访问控制
    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, IntByReference pulRetryCount);

    int SKF_UnblockPIN(Pointer hApplication, String szAdminPIN, String szNewUserPIN, IntByReference pulRetryCount);

    int SKF_ClearSecueState(Pointer hApplication);

    //容器管理
    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, IntByReference pulContainerType);

    // 密码服务
    // int SKF_ExportCertificate(Pointer hContainer, boolean bSignFlag, byte[] pbCert, IntByReference pulCertLen);
    // 接口中的boolean 都要改为int类型,1表示true,0表示false,如果是传boolean类型,不管是传true还是false,实际结果否是false的结果
    int SKF_ExportCertificate(Pointer hContainer, int bSignFlag, byte[] pbCert, IntByReference pulCertLen);

    //int SKF_ImportCertificate(Pointer hContainer, boolean bSignFlag, byte[] pbCert, IntByReference pulCertLen);
    // 接口中的boolean 都要改为int类型,1表示true,0表示false,如果是传boolean类型,不管是传true还是false,实际结果否是false的结果
    int SKF_ImportCertificate(Pointer hContainer, int bSignFlag, byte[] pbCert, IntByReference pulCertLen);

    int SKF_EncryptInit(Pointer hKey, BLOCKCIPHERPARAM 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);

    int SKF_DecryptInit(Pointer hKey, BLOCKCIPHERPARAM DecryptParam);

    int SKF_Decrypt(Pointer hKey, byte[] pbEncryptedData, int ulEncryptedLen, byte[] pbData, IntByReference pulDataLen);

    int SKF_DecryptFinal(Pointer hKey, byte[] pbDecryptedData, IntByReference pulDecryptedDataLen);

    //int SKF_ExportPublicKey(Pointer hContainer, boolean bSignFlag, byte[] pbBlob, IntByReference pulBlobLen);
    // 接口中的boolean 都要改为int类型,1表示true,0表示false,如果是传boolean类型,不管是传true还是false,实际结果否是false的结果
    int SKF_ExportPublicKey(Pointer hContainer, int 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_RSASignData(Pointer hContainer,byte[] pbData, int ulDataLen,byte[]pbSignature,IntByReference pulSignLen);

    int SKF_RSAVerify(Pointer hContainer,RSAPUBLICKEYBLOB pPubKey,byte[] pbData, int ulDataLen,byte[]pbSignature,int ulSignLen);

    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_RSAExportSessionKey(Pointer hContainer, int ulAlgId, RSAPUBLICKEYBLOB pPubKey, byte[] pData, IntByReference pulDataLen, PointerByReference phSessionKey);

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

    int SKF_ImportSessionKey(Pointer hCnt, int ulAlgId, byte[] pbWrapedData, int ulWrapedLen, PointerByReference hkey);

    int SKF_SetSymmKey(Pointer hDev, byte[] pbKey, int ulAlgID, PointerByReference phKey);

    int SKF_CloseHandle(Pointer hHandle);

    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;
      public byte[] Issuer = new byte;
      public byte[] Label = new byte;
      public byte[] SerialNumber = new byte;
      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;

      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;
      public int IVLen = 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 void setBlobCipherParam(byte[] IV, int ivLen, int PaddingType, int FeedBitLen){
   
            this.IVS = IV;
            this.IVLen = ivLen;
            this.PaddingType = PaddingType;//填充方式,0表示不填充,1表示按照PKCS5方式进行填充。
            this.FeedBitLen = FeedBitLen;
      }
    }

    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;
      public byte[] YCoordinate = new byte;

      @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 byte[] getEccPublicBlob() {
   
            byte[] eccPublicBlob = new byte;
            int bitLenInt = this.BitLen;
            byte[] bitLenBytes = new byte;
            bitLenBytes = (byte) (bitLenInt & 0xFF); // 最低有效字节
            bitLenBytes = (byte) ((bitLenInt >> 8) & 0xFF);
            bitLenBytes = (byte) ((bitLenInt >> 16)
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: Java调用UK动态库SKF接口(dll/so)——JNA的实现