/**
 * @name mTokenPlugin集成代码
 * @author Akay
 * @version 0.7.10
 * @date 2020.04.04
 * 
 * @description
 * ver 0.7.10 2020.04.04
 * 1. 新增获取设备序号
 * 2. 支持多Key
 *
 * ver 0.7.9 2020.01.08
 * 1. 支持SJK1137型号
 *
 * ver 0.7.8 2019.10.23
 * 1. 新增UKey适配
 *
 * ver 0.7.4  2019.09.18
 * 1. 新增证书生效，失效时间
 * 
 * ver 0.7.3  2019.08.19
 * 1. 获取证书使用者信息
 * 
 * ver 0.7.2  2019.08.08
 * 1. 新增远程解锁接口
 *
 * ver 0.7.1 2019.07.17
 * TODO: 未安装组件时，判断组件是否安装(暂定，未解决）
 * 
 * ver 0.7.0 2019.07.04
 * 1. 更新核心文件，解决多Key插入问题
 * 2. Ukey目前仅支持国密证书
 *
 * ver 0.6.3 2019.06.24
 * 1. 修复部分Bug
 * 
 * ver 0.6.1 2019.06.24
 * 1. 支持数字信封数据解密接口
 * 2. 修复加密接口错误部分。
 *
 * ver 0.6.0 2019.06.20
 * 1. 支持数字信封数据加密接口
 * 2. 暂不支持多Ukey
 * 
 * ver 0.5.1 2019.06.19
 * 1. 修正新Ukey引入导致的Bug
 * 
 * ver 0.5  2019.06.18
 * 1. 适配SJK1137型号Ukey
 * 
 * ver 0.4  2019.03.16
 * 1. 新增方法 枚举Ukey获取证书“G项信息”列表
 * 2. 新增方法 将“证书G项信息”转化为“证书名称”方法
 * 
 * ver 0.3  2018.12.10
 * 1. 新增修改Ukey密码的方法
 *
 * ver 0.2  2018.09.26
 * 1. 新增获取签名证书SN号的方法
 * 2. 修正部分Bug
 * 
 * ver 0.1 2018.09.21
 * 1. 搭建初步框架
 * 2. 完成签名功能
 * 
 */
function hunca_mToken_core() {

    var token = new mToken("mTokenPlugin");
    var certInfoList = null;
	var singleKey = 0;

	var libraryNameList = Array("GM3000"); 
    /**
     * 错误信息
     */
    var LAST_ERRORSTRING = "";

    /**
     * 证书用途
     */
    var KEY_SPEC_TYPE_ENCRYPT = 0;
    var KEY_SPEC_TYPE_SIGN = 1;

    /**
     * 摘要算法
     */
    var SGD_SM3 = 1;
    var SGD_SHA1 = 2;

    /**
     * 加密算法
     */
    //分组加密算法标识
    var SGD_SM1_ECB = 0x00000101;
    var SGD_SM1_CBC = 0x00000102;
    var SGD_SM1_CFB = 0x00000104;
    var SGD_SM1_OFB = 0x00000108;
    var SGD_SM1_MAC = 0x00000110;
    var SGD_SM4_ECB = 0x00000401;
    var SGD_SM4_CBC = 0x00000402;
    var SGD_SM4_CFB = 0x00000404;
    var SGD_SM4_OFB = 0x00000408;
    var SGD_SM4_MAC = 0x00000410;


    /**
     * 用户ID（固定）
     */
    var USER_ID = "1234567812345678";


    /**
     * 错误信息提示列表
     */
    var ERROR_MESSAGE_NOT_LOADLIBRARY = "控件加载失败,错误码:";
    var ERROR_MESSAGE_NOT_FIND_UKEY = "未找到UKey！\n1.请确认是否安装最新驱动!\n2.计算机是否插入CA UKey！";
    var ERROR_MSSSAGE_FIND_MORE_UKEY = "计算机插入多个UKey，请拔除多余“CA UKey”！";
    var ERROR_MESSAGE_NOT_INSTANCE_DEVICE = "USBKey实例化失败,请确认此UKey是否插入计算机!\n点击‘刷新’按钮，更新设备列表。\n错误码:";
    var ERROR_MESSAGE_USERPIN_LENGTH = "Ukey密码必须为4~16位！";
    var ERROR_MESSAGE_USERPIN_IS_ERROR = "UKey密码错误";
    var ERROR_MESSAGE_USERPIN_CHANGE_ERROR = "UKey密码修改失败";
    var ERROR_MESSAGE_KEY_NOT_EXIT = "UKey不存在,请确认此UKey是否插入计算机，并点击'刷新'按钮，更新设备列表！";
    var ERROR_MESSAGE_USERNAME_IS_NULL = "请点击‘刷新’按钮，更新设备列表并选择相应设备！";
    var ERROR_MESSAGE_KEY_EXPORT_CERT = "证书获取失败，请加检测Key中是否存在证书！";
    var ERROR_MESSAGE_SET_DIGEST_METHOD_ERROR = "设置摘要算法失败，请重新刷新浏览器！";
    var ERROR_MESSAGE_SET_USERID_ERROR = "设置用户ID失败，请重新刷新浏览器";
    var ERROR_MESSAGE_SIGN_ORIGINALDATA_IS_NULL = "签名失败，待签名原文不能为空";
    var ERROR_MESSAGE_SIGN_ERROR = "签名失败，返回错误码：";
    var ERROR_MESSAGE_USERNAMEGN_IS_NULL = "请点击‘刷新’按钮，更新设备列表并选择相应设备！";
    var ERROR_MESSAGE_USERNAMEGN_TO_USERNAME_ERROR = "证书G项信息转化证书名称失败，请点击“刷新”按钮！";
    var ERROR_MESSAGE_KEY_LIBRAY = "加载国密库失败！";
    var ERROR_MESSAGE_ENCRYPT_DATA_IS_NULL = "加密失败：待加密原文不能为空！";
    var ERROR_MESSAGE_DECRYPT_DATA_IS_NULL = "解密失败：待解密密文不能为空！";
    var ERROR_MESSAGE_DECRYPT_DATA_IS_ERROR = "解密失败：请确认密文是否完整！\n解密所采用的Ukey是否为加密时的Ukey！";
    var ERROR_MESSAGE_GET_REMOTEUNLOCKREQUEST_FAIL = "申请解锁请求失败！";
    var ERROR_MESSAGE_GET_REMOTEUNLOCKREQUEST_NOT_SUPPORT = "此型号Ukey不支持解锁！";
    var ERROR_MESSAGE_REMOTE_UNLOCK_FAIL = "Ukey解锁失败！";

    /**
     * 私有变量
     */
    var tokenInfoList = null;

    /**
     * 私有变量
     */
    var signResultSignData = null;
    var signResultCert = null;

    /**
     * 证书信息
     */
    var certSn = null; //证书Sn
    var cert_subject_GN = null; //证书Gn
    var cert_subject = null; //证书使用者
    var cert_validTime = null;    //证书失效时间
    var cert_notbeforetime = null;   //证书生效时间

    /**
     * 返回错误信息
     */
    this.Hunca_GetLastError = function () {
        return LAST_ERRORSTRING;
    }

    /**
     * 获取证书列表
     */
    this.Hunca_GetUserList = function () {
        var deviceArray = null;
        var containerName = null;
        var userName = null;
        var tmpInfo = null;

        signResultCert = null;
        signResultSignData = null;
        tokenInfoList = new Array(); //清空信息

        for (var index = 0; index < libraryNameList.length; index++) {
            libraryName = libraryNameList[index];
            if (!SOF_LoadLibrary(libraryName)) {
                continue;
            }

            deviceArray = SOF_EnumDevice();
            if (null == deviceArray) {
                continue;
            }

            for (var i = 0; i < deviceArray.length; i++) {
                var tokenInfo = new Object();
                //实例化设备失败
                if (!SOF_GetDeviceInstance(deviceArray[i])) {
                    break;
                }

                //获取设备信息
                tmpInfo = SOF_GetUserList();
                if (null != tmpInfo || tmpInfo.length != 0) {
                    containerName = tmpInfo[0][1];
                    userName = tmpInfo[0][0];

                    tokenInfo.libraryName = libraryName; //Ukey型号
                    tokenInfo.serial = deviceArray[i]; //设备序列号
                    tokenInfo.userName = userName; //证书名称
                    tokenInfo.containerName = containerName; //应用名称

                    tokenInfoList.push(tokenInfo);
                } else {
                    continue;
                }
                SOF_LogOut();
            }
        }

        //返回证书信息
        var userNameList = new Array();
        for (var i = 0; i < tokenInfoList.length; i++) {
            userNameList[i] = tokenInfoList[i].userName;
        }

        if (userNameList.length == 0) {
            LAST_ERRORSTRING = ERROR_MESSAGE_NOT_FIND_UKEY;
            return "";
        }

        return userNameList;
    }

    /**
     * 获取证书G项信息列表
     */
    this.Hunca_GetUserListGN = function () {
        var deviceArray = null;
        var containerName = null;
        var userName = null;
        var tmpInfo = null;
        var certB64 = null;
        var deviceSerial = "";

        signResultCert = null;
        signResultSignData = null;
        tokenInfoList = new Array(); //清空信息
        LAST_ERRORSTRING = "";

        for (var index = 0; index < libraryNameList.length; index++) {
            libraryName = libraryNameList[index];
            //加载控件
            if (!SOF_LoadLibrary(libraryName)) {
                continue;
            }

            deviceArray = SOF_EnumDevice();
            if (null == deviceArray) {
                continue;
            }

            for (var i = 0; i < deviceArray.length; i++) {
                cert_subject_GN = null;
                certSn = null;
                deviceSerial = deviceArray[i];

                var tokenInfo = new Object();

                //实例化设备失败
                if (!SOF_GetDeviceInstance(deviceSerial)) {
                    break;
                }

                //获取设备信息
                tmpInfo = SOF_GetUserList();
                if (null != tmpInfo || tmpInfo.length != 0) {
                    containerName = tmpInfo[0][1];
                    userName = tmpInfo[0][0];

                    tokenInfo.libraryName = libraryName;
                    tokenInfo.serial = deviceArray[i]; //设备序列号
                    tokenInfo.userName = userName; //证书名称
                    tokenInfo.containerName = containerName;
                } else {
                    continue;
                }

                //获取证书G项信息
                certB64 = SOF_ExportUserCert(tokenInfo.containerName, KEY_SPEC_TYPE_SIGN);
                if (SOF_GetCertInfo(certB64)) {
                    tokenInfo.subjectGN = cert_subject_GN; //设备证书G项目；
                } else {
                    continue;
                }

                tokenInfoList.push(tokenInfo);
                SOF_LogOut();
            }
        }

        //返回证书G项信息
        var userNameGNList = new Array();
        for (var i = 0; i < tokenInfoList.length; i++) {
            userNameGNList[i] = tokenInfoList[i].subjectGN;
        }

        if (userNameGNList.length == 0) {
            LAST_ERRORSTRING = ERROR_MESSAGE_NOT_FIND_UKEY;
            return "";
        }

	/*****
        if (userNameGNList.length > 1){
            LAST_ERRORSTRING = ERROR_MSSSAGE_FIND_MORE_UKEY;
            return "";
        }
	****/
        return userNameGNList;
    }

    /**
     * 将证书G项信息转化为证书名称
     */
    this.Hunca_userNameGNToUserName = function (userNameGN) {
        var userName = null;
        LAST_ERRORSTRING = "";
        if (null == userNameGN || userNameGN.length == 0) {
            LAST_ERRORSTRING = ERROR_MESSAGE_USERNAMEGN_IS_NULL;
        }

        for (var i = 0; i < tokenInfoList.length; i++) {
            if (userNameGN == tokenInfoList[i].subjectGN) {
                userName = tokenInfoList[i].userName;
                break;
            }
        }

        if (null == userName || userName.length == 0) {
            LAST_ERRORSTRING = ERROR_MESSAGE_USERNAMEGN_TO_USERNAME_ERROR;
            return null;
        }
        return userName;
    }

    this.Hunca_GenRemoteUnblockRequest = function (userName) {
        var tokenInfo = null; //Ukey设备信息
        var tempTokenInfo = null; //临时设备信息，循环遍历用
        var request = "";

        LAST_ERRORSTRING = "";

        //设备名称为空
        if (null == userName || userName.length == null) {
            LAST_ERRORSTRING = ERROR_MESSAGE_USERNAME_IS_NULL;
            return false;
        }

        //查找匹配的设备序列号
        if (null == tokenInfoList || tokenInfoList.length == 0) {
            LAST_ERRORSTRING = ERROR_MESSAGE_NOT_FIND_UKEY;
            return false;
        }

        //索引设备编号
        for (var i = 0; i < tokenInfoList.length; i++) {
            tempTokenInfo = tokenInfoList[i];
            if (tempTokenInfo.userName == userName) {
                tokenInfo = tempTokenInfo;
                break;
            }
        }

        //如果所选择的设备不存在
        if (null == tokenInfo) {
            LAST_ERRORSTRING = ERROR_MESSAGE_KEY_NOT_EXIT;
            return false;
        }

        //判断设备是否支持远程解锁
        if (tokenInfo.libraryName != "GM3000") {
            LAST_ERRORSTRING = ERROR_MESSAGE_GET_REMOTEUNLOCKREQUEST_NOT_SUPPORT;
            return false;
        }

        //加载库文件
        if (!SOF_LoadLibrary(tokenInfo.libraryName)) {
            LAST_ERRORSTRING = ERROR_MESSAGE_KEY_LIBRAY;
            return false;
        }

        //实例化设备
        if (!SOF_GetDeviceInstance(tokenInfo.serial)) {
            return false;
        }

        //枚举容器，并选择第一个容器
        if (SOF_GetUserList() == null) {
            return false;
        }

        //远程解锁
        request = SOF_GenRemoteUnblockRequest()

        return request;
    }

    this.HUnca_GetDeviceNumber = function(userName){
        var m_devNumber = null;

        //设备名称为空
        if (null == userName || userName.length == null) {
            LAST_ERRORSTRING = ERROR_MESSAGE_USERNAME_IS_NULL;
            return false;
        }

        //查找匹配的设备序列号
        if (null == tokenInfoList || tokenInfoList.length == 0) {
            LAST_ERRORSTRING = ERROR_MESSAGE_NOT_FIND_UKEY;
            return false;
        }

        //索引设备编号
        for (var i = 0; i < tokenInfoList.length; i++) {
            tempTokenInfo = tokenInfoList[i];
            if (tempTokenInfo.userName == userName) {
                tokenInfo = tempTokenInfo;
                break;
            }
        }

        //如果所选择的设备不存在
        if (null == tokenInfo) {
            LAST_ERRORSTRING = ERROR_MESSAGE_KEY_NOT_EXIT;
            return false;
        }

          //加载库文件
          if (!SOF_LoadLibrary(tokenInfo.libraryName)) {
            LAST_ERRORSTRING = ERROR_MESSAGE_KEY_LIBRAY;
            return false;
        }

        //实例化设备
        if (!SOF_GetDeviceInstance(tokenInfo.serial)) {
            return false;
        }
        m_devNumber =SOF_GetDeviceNumber();

        return m_devNumber + "";
    }

    this.Hunca_RemoteUnlockPIN = function (userName, response) {
        var tokenInfo = null; //Ukey设备信息
        var tempTokenInfo = null; //临时设备信息，循环遍历用
        var result = false;

        LAST_ERRORSTRING = "";

        //设备名称为空
        if (null == userName || userName.length == null) {
            LAST_ERRORSTRING = ERROR_MESSAGE_USERNAME_IS_NULL;
            return false;
        }

        //查找匹配的设备序列号
        if (null == tokenInfoList || tokenInfoList.length == 0) {
            LAST_ERRORSTRING = ERROR_MESSAGE_NOT_FIND_UKEY;
            return false;
        }

        //索引设备编号
        for (var i = 0; i < tokenInfoList.length; i++) {
            tempTokenInfo = tokenInfoList[i];
            if (tempTokenInfo.userName == userName) {
                tokenInfo = tempTokenInfo;
                break;
            }
        }

        //如果所选择的设备不存在
        if (null == tokenInfo) {
            LAST_ERRORSTRING = ERROR_MESSAGE_KEY_NOT_EXIT;
            return false;
        }

        //判断设备是否支持远程解锁
        if (tokenInfo.libraryName != "GM3000") {
            LAST_ERRORSTRING = ERROR_MESSAGE_GET_REMOTEUNLOCKREQUEST_NOT_SUPPORT;
            return false;
        }

        //加载库文件
        if (!SOF_LoadLibrary(tokenInfo.libraryName)) {
            LAST_ERRORSTRING = ERROR_MESSAGE_KEY_LIBRAY;
            return false;
        }

        //实例化设备
        if (!SOF_GetDeviceInstance(tokenInfo.serial)) {
            return false;
        }

        //枚举容器，并选择第一个容器
        if (SOF_GetUserList() == null) {
            return false;
        }

        //远程解锁
        result = SOF_RemoteUnlockPIN(response)
        return result;
    }

    /**
     * 修改Ukey密码
     */
    this.Hunca_ChangeUserPin = function (userName, oldUserPin, newUserPin) {
        var tokenInfo = null; //Ukey设备信息
        var tempTokenInfo = null; //临时设备信息，循环遍历用
        LAST_ERRORSTRING = "";

        //设备名称为空
        if (null == userName || userName.length == null) {
            LAST_ERRORSTRING = ERROR_MESSAGE_USERNAME_IS_NULL;
            return false;
        }

        //查找匹配的设备序列号
        if (null == tokenInfoList || tokenInfoList.length == 0) {
            LAST_ERRORSTRING = ERROR_MESSAGE_NOT_FIND_UKEY;
            return false;
        }

        //索引设备编号
        for (var i = 0; i < tokenInfoList.length; i++) {
            tempTokenInfo = tokenInfoList[i];
            if (tempTokenInfo.userName == userName) {
                tokenInfo = tempTokenInfo;
                break;
            }
        }

        //如果所选择的设备不存在
        if (null == tokenInfo) {
            LAST_ERRORSTRING = ERROR_MESSAGE_KEY_NOT_EXIT;
            return false;
        }

        //加载库文件
        if (!SOF_LoadLibrary(tokenInfo.libraryName)) {
            LAST_ERRORSTRING = ERROR_MESSAGE_KEY_LIBRAY;
        }

        //实例化设备
        if (!SOF_GetDeviceInstance(tokenInfo.serial)) {
            return false;
        }

        //修改密码
        if (!SOF_ChangeUserPin(oldUserPin, newUserPin)) {
            return false;
        }

        SOF_LogOut();
        return true;
    }

    /**
     * 对数据进行签名，并返回签名是否成功
     * @param {string} originalData 待签名原文
     * @param {string} userName Ukey用户名称
     * @param {string} userPin Ukey密码
     */
    this.Hunca_PKCS1 = function (originalData, userName, userPin) {
        var libraryName = null;
        var tokenInfo = null; //Ukey设备信息
        var tempTokenInfo = null; //临时设备信息，循环遍历用
        var certBase64 = null; //签名证书值

        LAST_ERRORSTRING = "";
        signResultInfo = null;
        certInfo = new Object();
        //设备名称为空
        if (null == userName || userName.length == null) {
            LAST_ERRORSTRING = ERROR_MESSAGE_USERNAME_IS_NULL;
            return false;
        }

        //查找匹配的设备序列号
        if (null == tokenInfoList || tokenInfoList.length == 0) {
            LAST_ERRORSTRING = ERROR_MESSAGE_NOT_FIND_UKEY;
            return false;
        }

        //索引设备编号
        for (var i = 0; i < tokenInfoList.length; i++) {
            tempTokenInfo = tokenInfoList[i];
            if (tempTokenInfo.userName == userName) {
                tokenInfo = tempTokenInfo;
                break;
            }
        }

        //如果所选择的设备不存在
        if (null == tokenInfo) {
            LAST_ERRORSTRING = ERROR_MESSAGE_KEY_NOT_EXIT;
            return false;
        }

        //加载库文件
        if (!SOF_LoadLibrary(tokenInfo.libraryName)) {
            LAST_ERRORSTRING = ERROR_MESSAGE_KEY_LIBRAY;
        }

        //实例化设备
        if (!SOF_GetDeviceInstance(tokenInfo.serial)) {
            return false;
        }

        //登陆应用
        if (!SOF_Login(userPin)) {
            return false;
        }

        //获取签名证书Base64
        certBase64 = SOF_ExportUserCert(tokenInfo.containerName, KEY_SPEC_TYPE_SIGN);
        if (null == certBase64) {
            return false;
        }

        //设置摘要算法
        if (!SOF_SetDigestMethod(SGD_SM3)) {
            return false;
        }

        if (!SOF_SetUserID()) {
            return false;
        }

        //进行签名
        if (!SOF_SignData(tokenInfo.containerName, SGD_SM3, originalData, certBase64)) {
            return false;
        }

        //获取证书信息
        if (!SOF_GetCertInfo(certBase64)) {
            return false;
        }

        SOF_LogOut();
        return true;
    }

    /**
     * 获取签名结果
     */
    this.Hunca_GetSignData = function () {
        return signResultSignData;
    }

    /**
     * 获取签名证书
     */
    this.Hunca_GetSignCert = function () {
        return signResultCert;
    }

    this.Hunca_GetSignCertSn = function () {
        return certSn
    }

    this.Hunca_GetSignCertSubject = function (){
        return cert_subject;
    }

    this.Hunca_GetValidTime = function(){
        return cert_validTime;
    }

    this.HUnca_GetNotBeforeTime = function(){
        return cert_notbeforetime;
    }
    /**
     * 处理设备中签名证书信息
     * @param {*} userName 
     */
    this.Hunca_DealCertInfo = function (userName) {
        var tokenInfo = null; //Ukey设备信息
        var tempTokenInfo = null; //临时设备信息，循环遍历用
        var certBase64 = null; //签名证书值

        LAST_ERRORSTRING = "";
        signResultInfo = null;
        certInfo = new Object();
        //设备名称为空
        if (null == userName || userName.length == null) {
            LAST_ERRORSTRING = ERROR_MESSAGE_USERNAME_IS_NULL;
            return false;
        }

        //查找匹配的设备序列号
        if (null == tokenInfoList || tokenInfoList.length == 0) {
            LAST_ERRORSTRING = ERROR_MESSAGE_NOT_FIND_UKEY;
            return false;
        }

        //索引设备编号
        for (var i = 0; i < tokenInfoList.length; i++) {
            tempTokenInfo = tokenInfoList[i];
            if (tempTokenInfo.userName == userName) {
                tokenInfo = tempTokenInfo;
                break;
            }
        }

        //如果所选择的设备不存在
        if (null == tokenInfo) {
            LAST_ERRORSTRING = ERROR_MESSAGE_KEY_NOT_EXIT;
            return false;
        }

        if (!SOF_LoadLibrary(tokenInfo.libraryName)) {
            LAST_ERRORSTRING = ERROR_MESSAGE_KEY_LIBRAY;
            return false;
        }

        //实例化设备
        if (!SOF_GetDeviceInstance(tokenInfo.serial)) {
            return false;
        }

        //导出证书
        certBase64 = SOF_ExportUserCert(tokenInfo.containerName, KEY_SPEC_TYPE_SIGN);
        if (null == certBase64 || certBase64.length == 0) {
            return false;
        }

        SOF_GetCertInfo(certBase64);
        SOF_LogOut();
        return true;
    }

    /**
     * 对数据进行数字信封加密
     * @param {string} inData 待加密原文
     * @param {string} userName Ukey用户名称
     * @param {string} EncryptMethod 对称加密方式
     * @param {string} EncryptIV 加密IV值
     * @returns {string} "",加密失败；非空，加密成功
     */
    this.Hunca_EncryptDataPKCS7 = function (inData, userName, EncryptMethod, EncryptIV) {
        var tokenInfo = null; //Ukey设备信息
        var tempTokenInfo = null; //临时设备信息，循环遍历用
        var certBase64 = null; //签名证书值
        var m_EncryptMethod = "",
            m_EncryptIV = "";

        LAST_ERRORSTRING = "";
        signResultInfo = null;
        certInfo = new Object();


        //设备名称为空
        if (null == userName || userName.length == null) {
            LAST_ERRORSTRING = ERROR_MESSAGE_USERNAME_IS_NULL;
            return "";
        }

        //查找匹配的设备序列号
        if (null == tokenInfoList || tokenInfoList.length == 0) {
            LAST_ERRORSTRING = ERROR_MESSAGE_NOT_FIND_UKEY;
            return "";
        }

        //索引设备编号
        for (var i = 0; i < tokenInfoList.length; i++) {
            tempTokenInfo = tokenInfoList[i];
            if (tempTokenInfo.userName == userName) {
                tokenInfo = tempTokenInfo;
                break;
            }
        }

        //如果所选择的设备不存在
        if (null == tokenInfo) {
            LAST_ERRORSTRING = ERROR_MESSAGE_KEY_NOT_EXIT;
            return "";
        }

        //加载链接库
        if (!SOF_LoadLibrary(tokenInfo.libraryName)) {
            LAST_ERRORSTRING = ERROR_MESSAGE_KEY_LIBRAY;
            return "";
        }

        //实例化设备
        if (!SOF_GetDeviceInstance(tokenInfo.serial)) {
            return "";
        }

        //导出加密证书
        certBase64 = SOF_ExportUserCert(tokenInfo.containerName, KEY_SPEC_TYPE_ENCRYPT);
        if (null == certBase64 || certBase64.length == 0) {
            return "";
        }

        //设置加密方式

        m_EncryptMethod = EncryptMethod + "";
        m_EncryptIV = EncryptIV + "";

        if (m_EncryptMethod == null || m_EncryptMethod.length == 0) {
            m_EncryptMethod = SGD_SM4_ECB;
            m_EncryptIV = "";
        }

        if (!SOF_SetEncryptMethodAndIV(m_EncryptMethod, m_EncryptIV)) {
            return "";
        }

        //对数据进行加密
        encryptData = SOF_EncryptDataPKCS7(certBase64, inData);

        SOF_LogOut();

        return encryptData;
    }

    /**
     * 对密文进行数字信封解密操作
     * @param {string}  encryptData 待解密密文
     * @param {string}  userName Ukey用户名称
     * @param {string}  userPin Ukey用户PIN码
     * @param {string}  EncryptMethod 对称加密方式
     * @param {string}  EncryptIV 加密IV值
     * @returns {string} "",加密失败；非空，加密成功
     */
    this.Hunca_DecryptDataPKCS7 = function (encryptData, userName, userPin, EncryptMethod, EncryptIV) {
        var tokenInfo = null; //Ukey设备信息
        var tempTokenInfo = null; //临时设备信息，循环遍历用
        var m_EncryptMethod = "",
            m_EncryptIV = "";
        var m_EncryptData = "";
        var m_DecryptData = "";
        var resData = "";

        LAST_ERRORSTRING = "";
        signResultInfo = null;
        certInfo = new Object();


        m_EncryptData = "" + encryptData;
        //设备名称为空
        if (null == userName || userName.length == null) {
            LAST_ERRORSTRING = ERROR_MESSAGE_USERNAME_IS_NULL;
            return "";
        }

        //查找匹配的设备序列号
        if (null == tokenInfoList || tokenInfoList.length == 0) {
            LAST_ERRORSTRING = ERROR_MESSAGE_NOT_FIND_UKEY;
            return "";
        }

        //索引设备编号
        for (var i = 0; i < tokenInfoList.length; i++) {
            tempTokenInfo = tokenInfoList[i];
            if (tempTokenInfo.userName == userName) {
                tokenInfo = tempTokenInfo;
                break;
            }
        }

        //如果所选择的设备不存在
        if (null == tokenInfo) {
            LAST_ERRORSTRING = ERROR_MESSAGE_KEY_NOT_EXIT;
            return "";
        }

        //加载链接库
        if (!SOF_LoadLibrary(tokenInfo.libraryName)) {
            LAST_ERRORSTRING = ERROR_MESSAGE_KEY_LIBRAY;
            return "";
        }

        //实例化设备
        if (!SOF_GetDeviceInstance(tokenInfo.serial)) {
            return "";
        }

        //登陆应用
        if (!SOF_Login(userPin)) {
            return "";
        }

        //设置加密方式
        m_EncryptMethod = EncryptMethod + "";
        m_EncryptIV = EncryptIV + "";
        if (m_EncryptMethod == null || m_EncryptMethod.length == 0) {
            m_EncryptMethod = SGD_SM4_ECB;
            m_EncryptIV = "";
        }

        if (!SOF_SetEncryptMethodAndIV(m_EncryptMethod, m_EncryptIV)) {
            return "";
        }

        m_DecryptData = SOF_DecryptDataPKCS7(tokenInfo.containerName, KEY_SPEC_TYPE_ENCRYPT, m_EncryptData);
        if (m_DecryptData.length == 0) {
            return "";
        }

        try {
            resData = _Base64decode(m_DecryptData);
        } catch (e) {
            resData = m_DecryptData;
            LAST_ERRORSTRING = "解密失败：Base64解码失败";
        }

        return resData;
    }

    /**
     * 加载底层文件
     * @returns {boolean} true,加载成功;false加载失败;
     */
    function SOF_LoadLibrary(libraryName) {
        var resultCode = 0;
        if (libraryName == "GM3000") {
            resultCode = token.SOF_LoadLibrary(token.GM3000);
        } else if (libraryName == "GM3000_HUNCA"){
            resultCode = token.SOF_LoadLibrary(token.GM3000_HUNCA);
        }
		else if (libraryName == "HT"){
			resultCode = token.SOF_LoadLibrary(token.HT);
		}
		else if (libraryName == "SJK1137") {
            resultCode = token.SOF_LoadLibrary(token.SJK1137);
        }

        if (resultCode != 0) {
            LAST_ERRORSTRING = ERROR_MESSAGE_NOT_LOADLIBRARY + token.SOF_GetLastError();
            return false;
        }
        return true;
    }

    /**
     * 枚举设备
     */
    function SOF_EnumDevice() {
        var deviceNameList = "";

        deviceNameList = token.SOF_EnumDevice();

        //检测是否插入USBKey
        if (null == deviceNameList || deviceNameList.length == 0) {
            LAST_ERRORSTRING = ERROR_MESSAGE_NOT_FIND_UKEY;
            return null;
        }

        return deviceNameList;
    }

    /**
     * 实例化设备，为后续一系列操作准备
     * @param {string} deviceName 设备名称
     */
    function SOF_GetDeviceInstance(deviceName) {
        var resultCode = 0;

        resultCode = token.SOF_GetDeviceInstance(deviceName, "");
        //设备未正常实例化
        if (resultCode != 0) {
            LAST_ERRORSTRING = ERROR_MESSAGE_NOT_INSTANCE_DEVICE + token.SOF_GetLastError();
            return false;
        }
        return true;
    }

    /**
     * 枚举应用中的容器
     */
    function SOF_GetUserList() {
        var userList = "";

        userList = token.SOF_GetUserList();
        if (null == userList || userList.length == 0) {
            LAST_ERRORSTRING = "USBkey中未找到证书！";
            return null;
        }

        return userList;
    }

    /**
     * 登陆应用，验证密码是否正确
     * @param {string} userPin 
     */
    function SOF_Login(userPin) {
        var resultCode = 0;
        var m_userPin = "" + userPin;
        var RetryCount = 0;

        if (null == m_userPin || m_userPin.length == 0) {
            LAST_ERRORSTRING = ERROR_MESSAGE_USERPIN_LENGTH;
            return false;
        }

        if (m_userPin.length < 4 || m_userPin.length > 16) {
            LAST_ERRORSTRING = ERROR_MESSAGE_USERPIN_LENGTH;
            return false;
        }

        resultCode = token.SOF_Login(m_userPin);
        if (resultCode != 0) {
            RetryCount = SOF_GetPinRetryCount();
            if (RetryCount > 0) {
                LAST_ERRORSTRING = ERROR_MESSAGE_USERPIN_IS_ERROR + "，还剩 " + RetryCount + " 次重试机会！";
            } else {
                LAST_ERRORSTRING = "UKey已经锁死，请联系管理员进行解锁！"
            }
            return false;
        }
        return true
    }

    /**
     * 修改UKey密码
     * @param {*} oldUserPin 
     * @param {*} newUserPin 
     */
    function SOF_ChangeUserPin(oldUserPin, newUserPin) {
        var resultCode = 0;
        var m_oldUserPin = "" + oldUserPin;
        var m_newUserPin = "" + newUserPin;
        var RetryCount = 0;

        if (null == m_oldUserPin || m_oldUserPin.length == 0) {
            LAST_ERRORSTRING = ERROR_MESSAGE_USERPIN_LENGTH;
            return false;
        }

        if (null == m_newUserPin || m_newUserPin.length == 0) {
            LAST_ERRORSTRING = ERROR_MESSAGE_USERPIN_LENGTH;
            return false;
        }

        if (m_oldUserPin.length < 4 || m_oldUserPin.length > 16) {
            LAST_ERRORSTRING = ERROR_MESSAGE_USERPIN_LENGTH;
            return false;
        }

        if (m_newUserPin.length < 4 || m_newUserPin.length > 16) {
            LAST_ERRORSTRING = ERROR_MESSAGE_USERPIN_LENGTH;
            return false;
        }

        resultCode = token.SOF_ChangePassWd(m_oldUserPin, m_newUserPin);
        if (resultCode != 0) {
            RetryCount = SOF_GetPinRetryCount();
            if (RetryCount > 0) {
                LAST_ERRORSTRING = ERROR_MESSAGE_USERPIN_CHANGE_ERROR + "，还剩 " + RetryCount + " 次重试机会！";
            } else {
                LAST_ERRORSTRING = "UKey已经锁死，请联系管理员进行解锁！"
            }
            return false;
        }
        return true;
    }

    /**
     * 返回重试次数
     */
    function SOF_GetPinRetryCount() {
        var retryCount = 0;
        retryCount = token.SOF_GetPinRetryCount();
        return retryCount;
    }

    function SOF_GetDeviceNumber(){
        var deviceNumber = null;
        deviceNumber = token.SOF_GetDeviceInfo(token.SGD_DEVICE_SERIAL_NUMBER);
        return deviceNumber;
    }

    /**
     * 导出证书值
     * @param {string} containerName 容器名称
     * @param {int} keySec 证书用途 
     */
    function SOF_ExportUserCert(containerName, keySec) {
        var certBase64;
        certBase64 = token.SOF_ExportUserCert(containerName, keySec);
        if (null == certBase64 || certBase64.length == 0) {
            LAST_ERRORSTRING = ERROR_MESSAGE_KEY_EXPORT_CERT;
            return null;
        }
        return certBase64;
    }

    /**
     * 设置加密算法
     * @param {*} EncryptMethod    设置加密算法
     * @param {*} EncryptIV 设置IV值
     */
    function SOF_SetEncryptMethodAndIV(EncryptMethod, EncryptIV) {
        var resCode = 1;

        if (EncryptMethod == undefined || EncryptMethod == null) {
            LAST_ERRORSTRING = "请设置加密方式！";
            return false;
        }

        resCode = token.SOF_SetEncryptMethodAndIV(EncryptMethod, _Base64encode(EncryptIV));
        if (resCode != 0) {
            LAST_ERRORSTRING = token.SOF_GetLastError();
            return false;
        }
        return true;
    }

    /**
     * 设置签名算法
     * @param {}} digestMethod 
     */
    function SOF_SetDigestMethod(digestMethod) {
        var resultCode = 0;
        resultCode = token.SOF_SetDigestMethod(digestMethod);
        if (resultCode != 0) {
            LAST_ERRORSTRING = ERROR_MESSAGE_SET_DIGEST_METHOD_ERROR;
            return false;
        }

        return true;
    }

    /**
     * 设置默认USERID
     */
    function SOF_SetUserID() {
        var resultCode = 0;
        resultCode = token.SOF_SetUserID(USER_ID);
        if (resultCode != 0) {
            LAST_ERRORSTRING = ERROR_MESSAGE_SET_USERID_ERROR;
            return false;
        }
        return true;
    }

    /**
     * 数字信封加密
     * @param {String} Base64EncodeCert 加密证书值
     * @param {String} inData 待加密原文
     * @returns {*} "",表示加密失败；非空，加密成功
     */
    function SOF_EncryptDataPKCS7(Base64EncodeCert, inData) {
        var encryptData = "";
        var inDataBase64 = "";
        var m_inData = "";

        m_inData = "" + inData;
        if (m_inData.length == 0) {
            LAST_ERRORSTRING = ERROR_MESSAGE_ENCRYPT_DATA_IS_NULL;
            return "";
        }

        inDataBase64 = _Base64encode(m_inData)
        encryptData = token.SOF_EncryptDataPKCS7(Base64EncodeCert, inDataBase64, inData.length);

        if (encryptData == null || encryptData.length == 0) {
            LAST_ERRORSTRING = "加密失败，" + token.SOF_GetLastError();
            return "";
        }
        return encryptData;
    }

    /**
     * 数字信封解密
     * @param {*} containerName 应用名称
     * @param {int} cerType 
     * @param {*} encrypedData 
     */
    function SOF_DecryptDataPKCS7(containerName, cerType, encrypedData) {
        var m_EncrypedData = "",
            m_DecryptData = "";

        m_EncrypedData = "" + encrypedData;
        if (containerName == null || containerName.length == 0) {
            LAST_ERRORSTRING = "应用名称不能为空！";
            return "";
        }

        if (m_EncrypedData.length == 0) {
            LAST_ERRORSTRING = ERROR_MESSAGE_DECRYPT_DATA_IS_NULL;
            return "";
        }

        try {
            m_DecryptData = token.SOF_DecryptDataPKCS7(containerName, cerType, m_EncrypedData);
        } catch (e) {
            m_DecryptData = "";
        }
        if (undefined == m_DecryptData || m_DecryptData == null || m_DecryptData == "") {
            LAST_ERRORSTRING = ERROR_MESSAGE_DECRYPT_DATA_IS_ERROR;
            return "";
        }

        return m_DecryptData;
    }

    /**
     * 数据签名
     * @param {*} containerName 
     * @param {*} ulKeySpec 
     * @param {*} data 
     * @param {*} certBase64 
     */
    function SOF_SignData(containerName, ulKeySpec, data, certBase64) {
        var signData = null;
        var b64Data = null;
        var m_data = "" + data;


        if (null == m_data || m_data.length == 0) {
            LAST_ERRORSTRING = ERROR_MESSAGE_SIGN_ORIGINALDATA_IS_NULL;
            return false;
        }

        b64Data = _Base64encode(m_data);
        signData = token.SOF_SignData(containerName, ulKeySpec, _Base64encode(b64Data), b64Data.length)
        if (null == signData || signData.length == 0) {
            LAST_ERRORSTRING = ERROR_MESSAGE_SIGN_ERROR + SOF_GetLastError();
            return false;
        }

        signResultCert = certBase64;
        signResultSignData = signData;

        return true;
    }

    /**
     * 导出证书
     * @param {*} certBase64 
     */
    function SOF_GetCertInfo(certBase64) {
        var str = null;
        var subject = null;
        var tmpList = null;
        var validTime = null;
        var notBeforetime = null;
        var key, value;

        if (null == certBase64 || certBase64.length == 0) {
            return false;
        }

        cert_subject_GN = "";
        certSn = "";
        cert_subject = "";

        str = token.SOF_GetCertInfo(certBase64, token.SGD_CERT_SERIAL);
        certSn = hexToDec(str);

        subject = token.SOF_GetCertInfo(certBase64, token.SGD_CERT_SUBJECT);
        cert_subject = subject;

        validTime = token.SOF_GetCertInfo(certBase64,token.SGD_CERT_VALID_TIME);
        cert_validTime = validTime;

        notBeforetime = token.SOF_GetCertInfo(certBase64,token.SGD_CERT_NOT_BEFORE);
        cert_notbeforetime = notBeforetime;
        
        tmpList = subject.split(',');
        for (var i = 0; i < tmpList.length; i++) {
            if (tmpList[i].indexOf("=") == -1) {
                continue;
            }

            key = tmpList[i].split('=')[0];
            value = tmpList[i].split('=')[1];

            if (key == 'GN') {
                cert_subject_GN = value;
                break;
            }
        }
        return true;
    }



    /**
     * 登出UKey
     */
    function SOF_LogOut() {
        token.SOF_LogOut();
    }

    /**
     * 生成解锁请求
     */
    function SOF_GenRemoteUnblockRequest() {
        var request = token.SOF_GenRemoteUnblockRequest();
        if (request == null || request == "") {
            LAST_ERRORSTRING = ERROR_MESSAGE_GET_REMOTEUNLOCKREQUEST_FAIL;
            return "";
        }

        return request;
    }

    function SOF_RemoteUnlockPIN(response) {
        var result = false;

        if (null == response || response.length == 0) {
            LAST_ERRORSTRING = "解锁失败解：响应不能为空！";
            return false;
        }

        result = token.SOF_RemoteUnblockPIN(response);
        if (result != 0) {
            LAST_ERRORSTRING = ERROR_MESSAGE_REMOTE_UNLOCK_FAIL;
            return false;
        } else {
            return true;
        }
    }

    function add(x, y, base) {
        var z = [];
        var n = Math.max(x.length, y.length);
        var carry = 0;
        var i = 0;
        while (i < n || carry) {
            var xi = i < x.length ? x[i] : 0;
            var yi = i < y.length ? y[i] : 0;
            var zi = carry + xi + yi;
            z.push(zi % base);
            carry = Math.floor(zi / base);
            i++;
        }
        return z;
    }

    function multiplyByNumber(num, x, base) {
        if (num < 0) return null;
        if (num == 0) return [];

        var result = [];
        var power = x;
        while (true) {
            if (num & 1) {
                result = add(result, power, base);
            }
            num = num >> 1;
            if (num === 0) break;
            power = add(power, power, base);
        }

        return result;
    }

    function parseToDigitsArray(str, base) {
        var digits = str.split('');
        var ary = [];
        for (var i = digits.length - 1; i >= 0; i--) {
            var n = parseInt(digits[i], base);
            if (isNaN(n)) return null;
            ary.push(n);
        }
        return ary;
    }


    function convertBase(str, fromBase, toBase) {
        var digits = parseToDigitsArray(str, fromBase);
        if (digits === null) return null;

        var outArray = [];
        var power = [1];
        for (var i = 0; i < digits.length; i++) {
            // invariant: at this point, fromBase^i = power
            if (digits[i]) {
                outArray = add(outArray, multiplyByNumber(digits[i], power, toBase), toBase);
            }
            power = multiplyByNumber(fromBase, power, toBase);
        }

        var out = '';
        for (var i = outArray.length - 1; i >= 0; i--) {
            out += outArray[i].toString(toBase);
        }
        return out;
    }

    function decToHex(decStr) {
        var hex = convertBase(decStr, 10, 16);
        return hex ? '0x' + hex : null;
    }


    function hexToDec(hexStr) {
        if (hexStr.substring(0, 2) === '0x') hexStr = hexStr.substring(2);
        hexStr = hexStr.toLowerCase();
        return convertBase(hexStr, 16, 10);
    }
}