package com.sunyard.ssp.modules.jna;

import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.ptr.IntByReference;
import com.sun.jna.ptr.PointerByReference;
import com.sunyard.ssp.modules.sysconf.cipherunit.enums.LibEnum;

/**
 * @author sunyard
 */
public interface CipherJna extends Library {

    /**
     * 加载动态库
     */
    CipherJna INSTANCE = Native.load(LibEnum.LIB_NAME.getValue(), CipherJna.class);


    /**
     * 打开设备
     * @param phDeviceHandle 设备句柄
     * @return int 响应码
     */
    int SDF_OpenDevice(PointerByReference phDeviceHandle);

    /**
     * 关闭设备
     * @param hDeviceHandle 设备句柄
     * @return int 响应码
     */
    int SDF_CloseDevice(Pointer hDeviceHandle);

    /**
     * 打开会话
     * @param hDeviceHandle 设备句柄
     * @param phSessionHandle 会话句柄
     * @return int 响应码
     */
    int SDF_OpenSession(Pointer hDeviceHandle, PointerByReference phSessionHandle);

    int SDF_ImportKey(Pointer hSessionHandle, byte[] pucKey, int uiKeyLen, PointerByReference phKeyhandle);

    /**
     * 关闭会话
     * @param hSessionHandle 会话句柄
     * @return int 响应码
     */
    int SDF_CloseSession(Pointer hSessionHandle);

    /**
     * 生成随机数
     * @param hSessionHandle 会话句柄
     * @param uiLength 生成随机数长度
     * @param pucRandom 存放随机数容器
     * @return int 响应码
     */
    int SDF_GenerateRandom(Pointer hSessionHandle, int uiLength, byte[] pucRandom);

    /**
     *  对称加密
     * @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
    );


    /**
     * 生成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
    );

    /**
     * 生成会话密钥并用外部ECC公钥加密输出,输出密钥句柄
     * @param hSessionHandle 会话句柄
     * @param uiKeyBits 密钥长度
     * @param uiAlgID 算法标识
     * @param pucPublicKey ECC公钥结构
     * @param pucKey 密钥密文
     * @param phKeyHandle 密钥句柄
     * @return int 响应码
     */
    int SDF_GenerateKeyWithEPK_ECC(
            Pointer hSessionHandle,
            int uiKeyBits,
            int uiAlgID,
            byte[] pucPublicKey,
            byte[] pucKey,
            PointerByReference phKeyHandle
    );


    /**
     * 杂凑运算初始化
     * @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 // 明文数据长度
    );

    /**
     * MAC 计算
     * @param phSessionHandle 会话句柄
     * @param hKeyHadnle 密钥句柄
     * @param uiAlgID 算法标识
     * @param pucIV IV数据
     * @param purData 待计算MAC的数据
     * @param pucDatalength 待计算MAC的数据长度
     * @param pucMAC MAC值
     * @param pucMACLength MAC值长度
     * @return
     */
    int SDF_CalculateMAC(Pointer phSessionHandle,
                     Pointer hKeyHadnle,
                     int uiAlgID,
                     byte[] pucIV,
                     byte[] purData,
                     int pucDatalength,
                     byte[] pucMAC,
                     IntByReference pucMACLength);

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

    /**
     * 外部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);

    /**
     * 密钥加密
     * @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);

    /**
     * 生成密钥协商数据
     * @param phSessionHandle 会话句柄
     * @param uiISKIndex 密码设备存储私钥的索引值
     * @param uiKeyBits 要求协商的密钥长度
     * @param pucSponsorID 参与密钥协商的发起方ID值
     * @param uiSponsorIDLength 发起方ID长度
     * @param pucSponsorPublicKey 返回的发起方ECC公钥结构
     * @param pucSponsorTmpPublicKey 返回的发起方临时ECC公钥结构
     * @param phAgreementHandle 返回的协商对象，用于计算协商密钥
     * @return int 响应码
     */
    int SDF_GenerateAgreementDataWithECC(Pointer phSessionHandle, int uiISKIndex, int uiKeyBits,
                                         String pucSponsorID, int uiSponsorIDLength,
                                         byte[] pucSponsorPublicKey, byte[] pucSponsorTmpPublicKey,
                                         PointerByReference phAgreementHandle);

    /**
     * 生成密钥协商数据并计算密钥
     * @param phSessionHandle 会话句柄
     * @param uiISKIndex 密码设备存储私钥的索引值
     * @param uiKeyBits 要求协商的密钥长度
     * @param pucResponseID 参与密钥协商的响应方ID值
     * @param uiResponseIDLength 响应方ID长度
     * @param pucSponsorID 参与密钥协商的发起方ID值
     * @param uiSponsorIDLength 发起方ID长度
     * @param pucSponsorPublicKey 发起方ECC公钥结构
     * @param pucSponsorTmpPublicKey 发起方临时ECC公钥结构
     * @param pucResponsePublicKey 响应方ECC公钥结构
     * @param pucResponseTmpPublicKey 响应方临时ECC公钥结构
     * @param phKeyhandle 返回的密钥句柄
     * @return
     */
    int SDF_GenerateAgreementDataAndKeyWithECC(
            Pointer phSessionHandle,
            int uiISKIndex,
            int uiKeyBits,
            String pucResponseID,
            int uiResponseIDLength,
            String pucSponsorID,
            int uiSponsorIDLength,
            byte[] pucSponsorPublicKey,
            byte[] pucSponsorTmpPublicKey,
            byte[] pucResponsePublicKey,
            byte[] pucResponseTmpPublicKey,
            PointerByReference phKeyhandle
    );

    /**
     * 获取私钥访问权
     * @param phSessionHandle 会话句柄
     * @param uiKeyIndex 密码设备存储私钥的索引值
     * @param pucPassword 使用私钥权限的标识码
     * @param uiPwdLength 私钥访问控制码长度，不少于８字节
     * @return int 响应码
     */
    int SDF_GetPrivateKeyAccessRight(Pointer phSessionHandle, int uiKeyIndex, String pucPassword, int uiPwdLength);

    /**
     * 释放私钥访问权
     * @param phSessionHandle 会话句柄
     * @param uiKeyIndex 密码设备存储私钥的索引值
     * @return int 响应码
     */
    int SDF_ReleasePrivateKeyAccessRight(Pointer phSessionHandle, int uiKeyIndex);
}
