package com.sunyard.chsm.sdf.lib;

import com.sun.jna.Library;
import com.sun.jna.Pointer;
import com.sun.jna.ptr.IntByReference;
import com.sun.jna.ptr.PointerByReference;
import com.sunyard.chsm.sdf.model.SDF_DeviceInfo;

/**
 * @author liulu
 * @since 2024/11/4
 */
public interface SdfLibrary extends Library {

    /**
     * 打开设备
     *
     * @param phDeviceHandle 返回设备句柄
     * @return 0 成功;   非0 失败,返回错误代码
     */
    int SDF_OpenDevice(PointerByReference phDeviceHandle);

    /**
     * 关闭设备
     *
     * @param hDeviceHandle 已打开的设备句柄
     * @return 0 成功;   非0 失败,返回错误代码
     */
    int SDF_CloseDevice(Pointer hDeviceHandle);

    /**
     * 创建会话
     *
     * @param hDeviceHandle   已打开的设备句柄
     * @param phSessionHandle 返回与密码设备建立的新会话句柄
     * @return 0 成功;   非0 失败,返回错误代码
     */
    int SDF_OpenSession(Pointer hDeviceHandle, PointerByReference phSessionHandle);

    /**
     * 关闭会话
     *
     * @param hSessionHandle 与密码设备已建立的会话句柄
     * @return 0 成功;   非0 失败,返回错误代码
     */
    int SDF_CloseSession(Pointer hSessionHandle);

    /**
     * 获取设备信息
     *
     * @param hSessionHandle 与设备建立的会话句柄
     * @param pstDeviceInfo  设备能力描述信息，内容及格式见设备信息定义
     * @return 0 成功;   非0 失败,返回错误代码
     */
    int SDF_GetDeviceInfo(Pointer hSessionHandle, SDF_DeviceInfo pstDeviceInfo);

    /**
     * 产生随机数
     *
     * @param hSessionHandle 与设备建立的会话句柄
     * @param uiLength       欲获取的随机数长度
     * @param pucRandom      缓冲区指针，用于存放获取的随机数
     * @return 0 成功;   非0 失败,返回错误代码
     */
    int SDF_GenerateRandom(Pointer hSessionHandle, int uiLength, byte[] pucRandom);


    /**
     * 生成ECC密钥对
     *
     * @param phSessionHandle 会话句柄
     * @param uiAlgID         算法标识
     * @param uiKeyBits       密钥长度
     * @param pucPublicKey    输出的ECC公钥结构
     * @param pucPrivateKey   输出的ECC私钥结构
     * @return int 响应码
     */
    int SDF_GenerateKeyPair_ECC(
            Pointer phSessionHandle,
            int uiAlgID,
            int uiKeyBits,
            byte[] pucPublicKey,
            byte[] pucPrivateKey
    );

    /**
     * 导出签名公钥
     *
     * @param phSessionHandle
     * @param uiKeyIndex
     * @param pucPublicKey
     * @return
     */
    int SDF_ExportSignPublicKey_ECC(Pointer phSessionHandle,
                                    int uiKeyIndex,
                                    byte[] pucPublicKey);

    /**
     * 导出加密公钥
     *
     * @param phSessionHandle
     * @param uiKeyIndex
     * @param pucPublicKey
     * @return
     */
    int SDF_ExportEncPublicKey_ECC(Pointer phSessionHandle,
                                   int uiKeyIndex,
                                   byte[] pucPublicKey);

    /**
     * 密钥加密
     *
     * @param phSessionHandle 会话句柄
     * @param uiAlgID         算法标识
     * @param pucPublicKey    ECC公钥结构
     * @param pucData         输入的数据明文
     * @param pucDatalength   输入的数据明文长度
     * @param pucEncData      输出的密文数据
     * @return int 响应码
     */
    int SDF_ExternalEncrypt_ECC(Pointer phSessionHandle, int uiAlgID, byte[] pucPublicKey, byte[] pucData, int pucDatalength, byte[] pucEncData);

    /**
     * 密钥解密
     *
     * @param phSessionHandle 会话句柄
     * @param uiAlgID         算法标识
     * @param pucPrivateKey   ECC私钥结构
     * @param pucEncData      输入的密文数据
     * @param pucDataOut      输出的数据明文
     * @param pucDatalength   输出的数据明文长度
     * @return int 响应码
     */
    int SDF_ExternalDecrypt_ECC(Pointer phSessionHandle, int uiAlgID, byte[] pucPrivateKey, byte[] pucEncData, byte[] pucDataOut, IntByReference pucDatalength);

    /**
     * 外部ECC签名
     *
     * @param phSessionHandle 会话句柄
     * @param uiAlgID         算法标识
     * @param pucPublicKey    ECC公钥结构
     * @param pucData         输入的数据明文
     * @param pucDataLength   输入的数据明文长度
     * @param pucECCSignature 输出的签名值数据
     * @return int 响应码
     */
    int SDF_ExternalSign_ECC(
            Pointer phSessionHandle,
            int uiAlgID,
            byte[] pucPublicKey,
            byte[] pucData,
            int pucDataLength,
            byte[] pucECCSignature
    );

    /**
     * 外部ECC验签
     *
     * @param phSessionHandle 会话句柄
     * @param uiAlgID         算法标识
     * @param pucPublicKey    ECC公钥结构
     * @param pucData         输入的数据明文
     * @param pucDataLength   输入的数据明文长度
     * @param pucECCSignature 输入的签名值数据
     * @return int 响应码
     */
    int SDF_ExternalVerify_ECC(Pointer phSessionHandle, int uiAlgID, byte[] pucPublicKey, byte[] pucData, int pucDataLength, byte[] pucECCSignature);

    /**
     * 基于ECC算法的数字信封转换
     *
     * @param hSessionHandle 与设备建立的会话句柄
     * @param uiKeyIndex     密码设备内部存储ECC密钥对索引值
     * @param uiAlgID        外部ECC公钥的算法标识 SGD_SM2_1
     * @param pucPublicKey   外部ECC公钥结构
     * @param pucEncDateIn   缓冲区指针，用于存放输入的会话密钥密文
     * @param pucEncDateOut  缓冲区指针，用于存放输出的会话密钥密文
     * @return 0 成功;   非0 失败,返回错误代码
     */
    int SDF_ExchangeDigitEnvelopeBaseOnECC(Pointer hSessionHandle, int uiKeyIndex, int uiAlgID, byte[] pucPublicKey, byte[] pucEncDateIn, byte[] pucEncDateOut);

    /**
     *
     * @param hSessionHandle 与设备建立的会话句柄
     * @param pucKey         缓冲区指针，用于存放输入的密钥密文
     * @param puiKeyLength   返回的密钥明文长度
     * @param phKeyHandle    返回的密钥句柄
     * @return 0 成功;   非0 失败,返回错误代码
     */
    int SDF_ImportKey(Pointer hSessionHandle, byte[] pucKey, int puiKeyLength, PointerByReference phKeyHandle);

    /**
     * 获取私钥使用权限
     *
     * @param hSessionHandle 与设备建立的会话句柄
     * @param uiKeyIndex     密码设备存储私钥的索引值
     * @param pucPassword    使用私钥权限的标识码
     * @param uiPwdLength    私钥访问控制码长度，不少于8字节
     * @return 0 成功;   非0 失败,返回错误代码
     */
    int SDF_GetPrivateKeyAccessRight(Pointer hSessionHandle, int uiKeyIndex, byte[] pucPassword, int uiPwdLength);

    /**
     * 导入会话密钥并用内部ECC私钥解密
     *
     * @param phSessionHandle
     * @param uiISKIndex
     * @param puckey
     * @param phKeyhandle
     * @return
     */
    int SDF_ImportKeyWithISK_ECC(Pointer phSessionHandle,
                                 int uiISKIndex,
                                 byte[] puckey,
                                 PointerByReference phKeyhandle);

    /**
     * 销毁会话密钥
     *
     * @param phSessionHandle
     * @param phKeyhandle
     * @return
     */
    int SDF_DestroyKey(Pointer phSessionHandle, PointerByReference phKeyhandle);


    /**
     * 对称加密
     *
     * @param phSessionHandle  会话句柄
     * @param hKeyHandle       密钥句柄
     * @param uiAlgID          算法标识
     * @param pucIV            IV数据
     * @param pucData          待加密数据
     * @param pucDataLength    待加密数据长度
     * @param pucEncData       存放密文容器
     * @param pucEncDataLength 密文长度
     * @return int 响应码
     */
    int SDF_Encrypt(
            Pointer phSessionHandle,
            Pointer hKeyHandle,
            int uiAlgID,
            byte[] pucIV,
            byte[] pucData,
            int pucDataLength,
            byte[] pucEncData,
            IntByReference pucEncDataLength
    );

    /**
     * 对称解密
     *
     * @param phSessionHandle 会话句柄
     * @param hKeyHandle      密钥句柄
     * @param uiAlgID         算法标识
     * @param pucIV           IV数据
     * @param purEncData      指向密文数据的指针
     * @param encDataLength   密文数据长度
     * @param pucData         输出明文数据
     * @param pucDataLength   输出明文数据长度
     * @return int 响应码
     */
    int SDF_Decrypt(
            Pointer phSessionHandle,
            Pointer hKeyHandle,
            int uiAlgID,
            byte[] pucIV,
            byte[] purEncData,
            int encDataLength,
            byte[] pucData,
            IntByReference pucDataLength
    );


    /**
     * 杂凑运算初始化
     *
     * @param phSessionHandle 会话句柄
     * @param uiAlgID         算法标识
     * @param pucPublicKey    ECC公钥结构
     * @param pucID           签名者的ID值
     * @param pucIDlength     签名者ID的长度
     * @return int 响应码
     */
    int SDF_HashInit(Pointer phSessionHandle, int uiAlgID, byte[] pucPublicKey, String pucID, int pucIDlength);

    /**
     * 多包杂凑运算
     *
     * @param phSessionHandle 会话句柄
     * @param pucData         输入的数据明文
     * @param uiDataLength    输入的数据明文长度
     * @return int 响应码
     */
    int SDF_HashUpdate(
            Pointer phSessionHandle, // 使用IntByReference，因为SessionHandle可能是引用类型的
            byte[] pucData, // 输入的明文数据作为字节数组
            int uiDataLength // 明文数据长度
    );

    /**
     * 杂凑运算结束
     *
     * @param phSessionHandle 会话句柄
     * @param pucHash         杂凑结果
     * @param pucHashLength   杂凑结果长度
     * @return int 响应码
     */
    int SDF_HashFinal(Pointer phSessionHandle, byte[] pucHash, IntByReference pucHashLength);


    int SDF_CalculateMAC(Pointer phSessionHandle,
                         Pointer hKeyHadnle,
                         int uiAlgID,
                         byte[] pucIV,
                         byte[] purData,
                         int pucDatalength,
                         byte[] pucMAC,
                         IntByReference pucMACLength);

}
