using System;
using System.Text;
using System.IO;
using HidSharp;
using System.Linq;
using System.Threading;
using System.Runtime.InteropServices;

//公共函数说明

//***查找加密锁 
//int FindPort(int start, ref string OutKeyPath);

//查找指定的加密锁(使用普通算法一)
//int FindPort_2(int start, int in_data, int verf_data, ref string OutKeyPath);

//***获到锁的版本
//int NT_GetIDVersion(ref short version,  string KeyPath);

//获到锁的扩展版本
//int NT_GetIDVersionEx(ref short version,  string KeyPath);

//***获到锁的ID
//int GetID(ref int id_1, ref int id_2, string KeyPath);

//***从加密锁中读取一批字节
//int YReadEx(Byte[] OutData, short Address, short mylen, string HKey, string LKey, string KeyPath);

//***从加密锁中读取一个字节数据，一般不使用
//int YRead(ref Byte OutData, short Address,string HKey, string LKey, string KeyPath);

//***写一批字节到加密锁中
//int YWriteEx(Byte[] InData, short Address, short mylen, string HKey, string LKey, string KeyPath);

//***写一个字节的数据到加密锁中，一般不使用
//int YWrite(Byte InData, short Address, string HKey, string LKey, string KeyPath);

//***从加密锁中读字符串
//int YReadString(ref string outstring, short Address, short mylen, string HKey, string LKey, string KeyPath);

//***写字符串到加密锁中
//int YWriteString(string InString, short Address, string HKey, string LKey, string KeyPath);

//***算法函数
//int sWriteEx(int in_data , ref int out_data , string KeyPath);
//int sWrite_2Ex(int in_data , ref int out_data ,string KeyPath);
//int sRead(ref int in_data, string KeyPath);
//int sWrite(int out_data, string KeyPath);
//int sWrite_2(int out_data, string KeyPath);

//***设置写密码
//int SetWritePassword(string W_HKey, string W_LKey, string new_HKey, string new_LKey, string KeyPath);

//***设置读密码
//int SetReadPassword(string W_HKey, string W_LKey, string new_HKey, string new_LKey, string KeyPath);

//'设置增强算法密钥一
//int SetCal_2(string Key , string KeyPath);

//使用增强算法一对字符串进行加密
//int EncString(string InString , ref string outstring , string KeyPath);

//使用增强算法一对二进制数据进行加密
// int Cal(Byte[] InBuf, Byte[] OutBuf, string KeyPath);

//'设置增强算法密钥二
//int SetCal_New(string Key , string KeyPath);

//使用增强算法二对字符串进行加密
//int EncString_New(string InString , ref string outstring , string KeyPath);

//使用增强算法二对二进制数据进行加密
// int Cal_New(Byte[] InBuf, Byte[] OutBuf, string KeyPath);

//***初始化加密锁函数
//int ReSet( string Path);

//***获取字符串长度
//int lstrlenA(string InString );
namespace SoftKey
{
    public class F2K
    {
        #region Fields

        private const ushort VID = 0x3689;
        private const ushort PID = 0x3689;
        private const ushort PID_NEW = 0X4040;
        private const ushort VID_NEW = 0X3689;
        private const ushort PID_NEW_2 = 0X4040;
        private const ushort VID_NEW_2 = 0X2020;
        private const short DIGCF_PRESENT = 0x2;
        private const short DIGCF_DEVICEINTERFACE = 0x10;
        private const short INVALID_HANDLE_VALUE = (-1);
        private const short ERROR_NO_MORE_ITEMS = 259;

        private const uint GENERIC_READ = 0x80000000;
        private const int GENERIC_WRITE = 0x40000000;
        private const uint FILE_SHARE_READ = 0x1;
        private const uint FILE_SHARE_WRITE = 0x2;
        private const uint OPEN_EXISTING = 3;
        private const uint FILE_ATTRIBUTE_NORMAL = 0x80;
        private const uint INFINITE = 0xFFFF;

        private const short MAX_LEN = 2031;

        public const int FAILEDGENKEYPAIR = -21;
        public const int FAILENC = -22;
        public const int FAILDEC = -23;
        public const int FAILPINPWD = -24;
        public const int USBStatusFail = -50; //USB操作失败，可能是没有找到相关的指令
        private const int FUNCTION_LENGTH_NAME_MORE_THEN_25 = -79;
        private const int NOUSBKEY = -92;
        private const int CANNOT_OPEN_BIN_FILE = -8017;
        private const int CAN_NOT_READ_FILE = -8026;
        private const int OVER_KEY_LEN = 8025;
        private const int OVER_BIND_SIZE = -8035; //绑定电脑的数据超过最大绑定值


        public const int SM2_ADDBYTE = 97; //加密后的数据会增加的长度
        public const int MAX_ENCLEN = 128; //最大的加密长度分组
        public const int MAX_DECLEN = (MAX_ENCLEN + SM2_ADDBYTE); //最大的解密长度分组
        public const int SM2_USENAME_LEN = 80; // '最大的用户名长度


        public const int ECC_MAXLEN = 32;
        public const int PIN_LEN = 16;

        private const Byte GETVERSION = 0x01;
        private const Byte GETID = 0x02;
        private const Byte GETVEREX = 0x05;
        private const Byte CAL_TEA = 0x08;
        private const Byte SET_TEAKEY = 0x09;
        private const Byte READBYTE = 0x10;
        private const Byte WRITEBYTE = 0x11;
        private const Byte YTREADBUF = 0x12;
        private const Byte YTWRITEBUF = 0x13;
        private const Byte MYRESET = 0x20;
        private const Byte YTREBOOT = 0x24;
        private const Byte SET_ECC_PARA = 0x30;
        private const Byte GET_ECC_PARA = 0x31;
        private const Byte SET_ECC_KEY = 0x32;
        private const Byte GET_ECC_KEY = 0x33;
        private const Byte MYENC = 0x34;
        private const Byte MYDEC = 0X35;
        private const Byte SET_PIN = 0X36;
        private const Byte GEN_KEYPAIR = 0x37;
        private const Byte YTSIGN = 0x51;
        private const Byte YTVERIFY = 0x52;
        private const Byte GET_CHIPID = 0x53;

        private const Byte YTSIGN_2 = 0x53;

        //D8定义
        private const Byte MAX_KEY_LEN = 16;
        private const Byte MAX_FUNNAME = 25;
        private const Byte MAX_BUF_SIZE = 255;
        private const Byte DOWNLOAD_SIZE = (MAX_BUF_SIZE - 1 - 1 - 1); //一个字节长度，一个字节命令，一个字节报告
        private const Byte TRANSFER_VAR_SIZE = (MAX_BUF_SIZE - 1 - 1 - 4); //一个字节长度，一个字节命令，一个字节报告,4个字节内存起始地址
        private const Byte GETDATA_BUF_SIZE = (MAX_BUF_SIZE - 2 - 1 - 1); //2个字节错误码，1个字节长度是否完成，一个字节为多出来的
        private const Byte VERF_CODE_SIZE = 8;
        private const byte NEW_PWD_LEN = 9;

        private const byte
            NEW_EPROM_TRANSFER_SIZE =
                (MAX_BUF_SIZE - (1 + 1 + sizeof(short) + 1 + 2 * NEW_PWD_LEN)); //一个字节报告,一个字节命令，二个字节地址，一个字节长度，2*9个字节密码，

        private const Byte MAX_BIND_MAC_SIZE = 200;

        private const Byte GET_LIMIT_DATE = 0x71;
        private const Byte SET_LIMIT_DATE = 0x72;
        private const Byte GET_USER_ID = 0x73;
        private const Byte GET_LEAVE_NUMBER = 0x74;
        private const Byte CHECK_NUMBER = 0x75;
        private const Byte SET_NUMBER_AUTH = 0x76;
        private const Byte SET_BIND_AUTH = 0x77;
        private const Byte SET_DATE_AUTH = 0x78;
        private const Byte CHECK_DATE = 0x79;
        private const Byte CHECK_BIND = 0x7A;
        private const Byte GET_LEAVE_DAYS = 0x7B;
        private const Byte GET_BIND_INFO = 0x7C;
        private const Byte YTDOWNLOAD = 0x80;
        private const Byte START_DOWNLOAD = 0x81;
        private const Byte RUN_FUNCTION = 0x82;
        private const Byte SET_VAR = 0x84;
        private const Byte GET_VAR = 0x85;
        private const Byte SET_DOWNLOAD_KEY = 0x86;
        private const Byte OPEN_KEY = 0x87;
        private const Byte CLOSE_KEY = 0x88;
        private const Byte COUNTINU_RUNCTION = 0x89;
        private const Byte GET_API_PARAM = 0x8A;
        private const Byte SET_API_PARAM = 0x8B;
        private const Byte GETFUNCVER = 0x8C;
        private const Byte WRITE_NEW_EPROM = 0x8D;
        private const Byte READ_NEW_EPROM = 0x8E;
        private const Byte SET_PWD = 0x8F;


        private UInt16 UInt16 = sizeof(UInt16);

        public int MAX_TIMEOUT = 5;

        #endregion

        //以下函数用于将字节数组转化为宽字符串
        public static string ByteConvertString(Byte[] buffer)
        {
            char[] null_string = { '\0', '\0' };
            System.Text.Encoding encoding = System.Text.Encoding.Default;
            return encoding.GetString(buffer).TrimEnd(null_string);
        }

        //以下用于将16进制字符串转化为无符号长整型
        private uint HexToInt(string s)
        {
            string[] hexch =
            {
                "0", "1", "2", "3", "4", "5", "6", "7",
                "8", "9", "A", "B", "C", "D", "E", "F"
            };
            s = s.ToUpper();
            int i, j;
            int r, n, k;
            string ch;

            k = 1;
            r = 0;
            for (i = s.Length; i > 0; i--)
            {
                ch = s.Substring(i - 1, 1);
                n = 0;
                for (j = 0; j < 16; j++)
                    if (ch == hexch[j])
                        n = j;
                r += (n * k);
                k *= 16;
            }

            return unchecked((uint)r);
        }

        private int HexStringToByteArray(string InString, ref Byte[] b)
        {
            return HexStringToByteArrayEx(InString, ref b, 0);
        }

        private int HexStringToByteArrayEx(string InString, ref Byte[] b, int pos)
        {
            int nlen;
            int retutn_len;
            int n, i;
            string temp;
            nlen = InString.Length;
            if (nlen < 16) retutn_len = 16;
            retutn_len = nlen / 2;
            i = 0;
            for (n = 0; n < nlen; n = n + 2)
            {
                temp = InString.Substring(n, 2);
                b[i + pos] = (Byte)HexToInt(temp);
                i = i + 1;
            }

            return retutn_len;
        }

        public void EnCode(Byte[] inb, Byte[] outb, string Key)
        {
            UInt32 cnDelta, y, z, a, b, c, d, temp_2;
            UInt32[] buf = new UInt32[16];
            int n, i, nlen;
            UInt32 sum;
            //UInt32 temp, temp_1;
            string temp_string;


            cnDelta = 2654435769;
            sum = 0;

            nlen = Key.Length;
            i = 0;
            for (n = 1; n <= nlen; n = n + 2)
            {
                temp_string = Key.Substring(n - 1, 2);
                buf[i] = HexToInt(temp_string);
                i = i + 1;
            }

            a = 0;
            b = 0;
            c = 0;
            d = 0;
            for (n = 0; n <= 3; n++)
            {
                a = (buf[n] << (n * 8)) | a;
                b = (buf[n + 4] << (n * 8)) | b;
                c = (buf[n + 4 + 4] << (n * 8)) | c;
                d = (buf[n + 4 + 4 + 4] << (n * 8)) | d;
            }


            y = 0;
            z = 0;
            for (n = 0; n <= 3; n++)
            {
                temp_2 = inb[n];
                y = (temp_2 << (n * 8)) | y;
                temp_2 = inb[n + 4];
                z = (temp_2 << (n * 8)) | z;
            }


            n = 32;

            while (n > 0)
            {
                sum = cnDelta + sum;

                /*temp = (z << 4) & 0xFFFFFFFF;
                temp = (temp + a) & 0xFFFFFFFF;
                temp_1 = (z + sum) & 0xFFFFFFFF;
                temp = (temp ^ temp_1) & 0xFFFFFFFF;
                temp_1 = (z >> 5) & 0xFFFFFFFF;
                temp_1 = (temp_1 + b) & 0xFFFFFFFF;
                temp = (temp ^ temp_1) & 0xFFFFFFFF;
                temp = (temp + y) & 0xFFFFFFFF;
                y = temp & 0xFFFFFFFF;*/
                y += ((z << 4) + a) ^ (z + sum) ^ ((z >> 5) + b);

                /*temp = (y << 4) & 0xFFFFFFFF;
                temp = (temp + c) & 0xFFFFFFFF;
                temp_1 = (y + sum) & 0xFFFFFFFF;
                temp = (temp ^ temp_1) & 0xFFFFFFFF;
                temp_1 = (y >> 5) & 0xFFFFFFFF;
                temp_1 = (temp_1 + d) & 0xFFFFFFFF;
                temp = (temp ^ temp_1) & 0xFFFFFFFF;
                temp = (z + temp) & 0xFFFFFFFF;
                z = temp & 0xFFFFFFFF;*/
                z += ((y << 4) + c) ^ (y + sum) ^ ((y >> 5) + d);
                n = n - 1;
            }

            for (n = 0; n <= 3; n++)
            {
                outb[n] = System.Convert.ToByte((y >> (n * 8)) & 255);
                outb[n + 4] = System.Convert.ToByte((z >> (n * 8)) & 255);
            }
        }

        public void DeCode(Byte[] inb, Byte[] outb, string Key)
        {
            UInt32 cnDelta, y, z, a, b, c, d, temp_2;
            UInt32[] buf = new UInt32[16];
            int n, i, nlen;
            UInt32 sum;
            //UInt32 temp, temp_1;
            string temp_string;


            cnDelta = 2654435769;
            sum = 0xC6EF3720;

            nlen = Key.Length;
            i = 0;
            for (n = 1; n <= nlen; n = n + 2)
            {
                temp_string = Key.Substring(n - 1, 2);
                buf[i] = HexToInt(temp_string);
                i = i + 1;
            }

            a = 0;
            b = 0;
            c = 0;
            d = 0;
            for (n = 0; n <= 3; n++)
            {
                a = (buf[n] << (n * 8)) | a;
                b = (buf[n + 4] << (n * 8)) | b;
                c = (buf[n + 4 + 4] << (n * 8)) | c;
                d = (buf[n + 4 + 4 + 4] << (n * 8)) | d;
            }


            y = 0;
            z = 0;
            for (n = 0; n <= 3; n++)
            {
                temp_2 = inb[n];
                y = (temp_2 << (n * 8)) | y;
                temp_2 = inb[n + 4];
                z = (temp_2 << (n * 8)) | z;
            }


            n = 32;

            while (n-- > 0)
            {
                z -= ((y << 4) + c) ^ (y + sum) ^ ((y >> 5) + d);
                y -= ((z << 4) + a) ^ (z + sum) ^ ((z >> 5) + b);
                sum -= cnDelta;
            }

            for (n = 0; n <= 3; n++)
            {
                outb[n] = System.Convert.ToByte((y >> (n * 8)) & 255);
                outb[n + 4] = System.Convert.ToByte((z >> (n * 8)) & 255);
            }
        }


        public string StrEnc(string InString, string Key) //使用增强算法，加密字符串
        {
            Byte[] b, outb;
            Byte[] temp = new Byte[8], outtemp = new Byte[8];
            int n, i, nlen, outlen;
            string outstring;
            byte[] SrcbyteArray = System.Text.Encoding.Default.GetBytes(InString);

            nlen = SrcbyteArray.Length + 1;
            if (nlen < 8)
                outlen = 8;
            else
                outlen = nlen;
            b = new byte[outlen];
            outb = new byte[outlen];

            Array.Copy(SrcbyteArray, b, SrcbyteArray.Length);

            b.CopyTo(outb, 0);

            for (n = 0; n <= outlen - 8; n = n + 8)
            {
                for (i = 0; i < 8; i++) temp[i] = b[i + n];
                EnCode(temp, outtemp, Key);
                for (i = 0; i < 8; i++) outb[i + n] = outtemp[i];
            }

            outstring = "";
            for (n = 0; n <= outlen - 1; n++)
            {
                outstring = outstring + outb[n].ToString("X2");
            }

            return outstring;
        }

        public string StrDec(string InString, string Key) //使用增强算法，加密字符串
        {
            Byte[] b, outb;
            Byte[] temp = new Byte[8], outtemp = new Byte[8];
            int n, i, nlen, outlen;
            string temp_string;
            String c_str;


            nlen = InString.Length;
            if (nlen < 16) outlen = 16;
            outlen = nlen / 2;
            b = new Byte[outlen];
            outb = new Byte[outlen];

            i = 0;
            for (n = 1; n <= nlen; n = n + 2)
            {
                temp_string = InString.Substring(n - 1, 2);
                b[i] = System.Convert.ToByte(HexToInt(temp_string));
                i = i + 1;
            }

            b.CopyTo(outb, 0);

            for (n = 0; n <= outlen - 8; n = n + 8)
            {
                for (i = 0; i < 8; i++) temp[i] = b[i + n];
                DeCode(temp, outtemp, Key);
                for (i = 0; i < 8; i++) outb[i + n] = outtemp[i];
            }

            c_str = ByteConvertString(outb);
            return c_str;
        }

        private bool isfindmydevice(int pos, ref string OutPath)
        {
            var list = HidSharp.DeviceList.Local;
            var hidDeviceList = list.GetHidDevices(VID, PID).ToArray();
            if (hidDeviceList.Length > pos)
            {
                OutPath = hidDeviceList[pos].DevicePath;
                return true;
            }

            pos = pos - hidDeviceList.Length;
            hidDeviceList = list.GetHidDevices(VID_NEW, PID_NEW).ToArray();
            if (hidDeviceList.Length > pos)
            {
                OutPath = hidDeviceList[pos].DevicePath;
                return true;
            }

            pos = pos - hidDeviceList.Length;
            hidDeviceList = list.GetHidDevices(VID_NEW_2, PID_NEW_2).ToArray();
            if (hidDeviceList.Length > pos)
            {
                OutPath = hidDeviceList[pos].DevicePath;
                return true;
            }

            return false;
        }

        private int NT_FindPort(int start, ref string OutPath)
        {
            if (!isfindmydevice(start, ref OutPath))
            {
                return -92;
            }

            return 0;
        }

        private int NT_FindPort_2(int start, int in_data, int verf_data, ref string OutPath)
        {
            int pos;
            int out_data = 0;
            int ret;
            for (pos = start; pos < 256; pos++)
            {
                if (!isfindmydevice(pos, ref OutPath)) return -92;
                ret = WriteDword(in_data, OutPath);
                if (ret != 0) continue;
                ret = ReadDword(ref out_data, OutPath);
                if (ret != 0) continue;
                if (out_data == verf_data)
                {
                    return 0;
                }
            }

            return (-92);
        }

        private int OpenMydivece(out HidStream hidStream, string Path)
        {
            var list = HidSharp.DeviceList.Local;
            var hidDeviceList = list.GetHidDevices(VID, PID).ToArray();
            foreach (HidDevice dev in hidDeviceList)
            {
                if (Path.CompareTo(dev.DevicePath) == 0)
                {
                    if (dev.TryOpen(out hidStream)) return 0;
                    else return -92;
                }
            }

            hidDeviceList = list.GetHidDevices(VID_NEW, PID_NEW).ToArray();
            foreach (HidDevice dev in hidDeviceList)
            {
                if (Path.CompareTo(dev.DevicePath) == 0)
                {
                    if (dev.TryOpen(out hidStream)) return 0;
                    else return -92;
                }
            }

            hidDeviceList = list.GetHidDevices(VID_NEW_2, PID_NEW_2).ToArray();
            foreach (HidDevice dev in hidDeviceList)
            {
                if (Path.CompareTo(dev.DevicePath) == 0)
                {
                    if (dev.TryOpen(out hidStream)) return 0;
                    else return -92;
                }
            }

            hidStream = null;
            return -92;
        }

        private bool GetFeature(HidStream hidStream, ref Byte[] array_out, int out_len)
        {
            int count = 0;
            out_len = hidStream.Device.GetMaxFeatureReportLength();
            retry:
            array_out[0] = 1;
            try
            {
                if (out_len != 0)
                {
                    hidStream.GetFeature(array_out, 0, hidStream.Device.GetMaxFeatureReportLength());
                }
                else
                {
                    hidStream.GetFeature(array_out);
                }
            }
            catch
            {
                count++;
                if (count == MAX_TIMEOUT) return false;
                goto retry;
            }

            return true;
        }

        private bool SetFeature(HidStream hidStream, Byte[] array_in, int in_len)
        {
            array_in[0] = 2;
            try
            {
                hidStream.SetFeature(array_in);
            }
            catch
            {
                return false;
            }

            return true;
        }

        private int TransferData(Byte[] array_in, int in_len, ref Byte[] array_out, int out_len, string Path)
        {
            HidStream hUsbDevice;
            Byte[] array_In_257 = new Byte[257];
            Byte[] array_In_21 = new Byte[0x15];
            Byte[] array_out_257 = new Byte[257];
            if (OpenMydivece(out hUsbDevice, Path) != 0) return -92;
            Semaphore sem;
            sem = new Semaphore(1, 1);
            sem.WaitOne();
            try
            {
                if (in_len > 0)
                {
                    Array.Copy(array_in, array_In_257,
                        array_in.Length < array_In_257.Length ? array_in.Length : array_In_257.Length);
                    if (!SetFeature(hUsbDevice, array_In_257, in_len))
                    {
                        Array.Copy(array_in, 0, array_In_21, 0, 0x15);
                        if (!SetFeature(hUsbDevice, array_In_21, in_len))
                        {
                            return -93;
                        }
                    }
                }

                if (out_len > 0)
                {
                    if (!GetFeature(hUsbDevice, ref array_out_257, out_len))
                    {
                        return -94;
                    }
                }
            }
            finally
            {
                sem.Release(1);
            }

            if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
            {
                Array.Copy(array_out_257, 1, array_out, 0, out_len);
            }
            else
            {
                Array.Copy(array_out_257, 0, array_out, 0, out_len);
            }

            return 0;
        }

        private int NT_Read(ref Byte ele1, ref Byte ele2, ref Byte ele3, ref Byte ele4, string Path)
        {
            Byte[] array_in = new Byte[257];
            Byte[] array_out = new Byte[257];
            int ret = TransferData(array_in, 0, ref array_out, 5, Path);
            ele1 = array_out[0];
            ele2 = array_out[1];
            ele3 = array_out[2];
            ele4 = array_out[3];
            return ret;
        }

        private int NT_Write(Byte ele1, Byte ele2, Byte ele3, Byte ele4, string Path)
        {
            Byte[] array_in = new Byte[257];
            Byte[] array_out = new Byte[257];
            array_in[1] = 3;
            array_in[2] = ele1;
            array_in[3] = ele2;
            array_in[4] = ele3;
            array_in[5] = ele4;
            int ret = TransferData(array_in, 5, ref array_out, 0, Path);
            return ret;
        }

        private int NT_Write_2(Byte ele1, Byte ele2, Byte ele3, Byte ele4, string Path)
        {
            Byte[] array_in = new Byte[257];
            Byte[] array_out = new Byte[257];
            array_in[1] = 4;
            array_in[2] = ele1;
            array_in[3] = ele2;
            array_in[4] = ele3;
            array_in[5] = ele4;
            int ret = TransferData(array_in, 5, ref array_out, 0, Path);
            return ret;
        }

        private int GetIDVersion(ref short Version, string Path)
        {
            Byte[] array_in = new Byte[257];
            Byte[] array_out = new Byte[257];
            array_in[1] = 1;
            int ret = TransferData(array_in, 1, ref array_out, 1, Path);
            Version = array_out[0];
            return ret;
        }

        private int NT_GetID(ref int ID_1, ref int ID_2, string Path)
        {
            int[] t = new int[8];
            Byte[] array_in = new Byte[257];
            Byte[] array_out = new Byte[257];

            array_in[1] = 2;
            int ret = TransferData(array_in, 1, ref array_out, 8, Path);
            t[0] = array_out[0];
            t[1] = array_out[1];
            t[2] = array_out[2];
            t[3] = array_out[3];
            t[4] = array_out[4];
            t[5] = array_out[5];
            t[6] = array_out[6];
            t[7] = array_out[7];
            ID_1 = t[3] | (t[2] << 8) | (t[1] << 16) | (t[0] << 24);
            ID_2 = t[7] | (t[6] << 8) | (t[5] << 16) | (t[4] << 24);
            return ret;
        }


        private int Y_Read(Byte[] OutData, int address, int nlen, Byte[] password, string Path, int pos)
        {
            int addr_l;
            int addr_h;
            int n;
            Byte[] array_in = new Byte[512];
            Byte[] array_out = new Byte[512];
            if ((address > MAX_LEN) || (address < 0)) return -81;
            if ((nlen > 255)) return -87;
            if ((nlen + address) > MAX_LEN) return -88;
            addr_h = (address >> 8) * 2;
            addr_l = address & 255;


            array_in[1] = 0x10;
            array_in[2] = (Byte)addr_h;
            array_in[3] = (Byte)addr_l;
            array_in[4] = (Byte)nlen;
            for (n = 0; n <= 7; n++)
            {
                array_in[5 + n] = password[n];
            }

            int ret = TransferData(array_in, 13, ref array_out, nlen + 1, Path);
            if (array_out[0] != 0)
            {
                return -83;
            }

            for (n = 0; n < nlen; n++)
            {
                OutData[n + pos] = array_out[n + 1];
            }

            return ret;
        }

        private int Y_Write(Byte[] indata, int address, int nlen, Byte[] password, string Path, int pos)
        {
            int addr_l;
            int addr_h;
            int n;
            Byte[] array_in = new Byte[512];
            Byte[] array_out = new Byte[512];
            if ((nlen > 255)) return -87;
            if ((address + nlen - 1) > (MAX_LEN + 17) || (address < 0)) return -81;
            addr_h = (address >> 8) * 2;
            addr_l = address & 255;


            array_in[1] = 0x11;
            array_in[2] = (Byte)addr_h;
            array_in[3] = (Byte)addr_l;
            array_in[4] = (Byte)nlen;
            for (n = 0; n <= 7; n++)
            {
                array_in[5 + n] = password[n];
            }

            for (n = 0; n < nlen; n++)
            {
                array_in[13 + n] = indata[n + pos];
            }

            int ret = TransferData(array_in, 13, ref array_out, 2, Path);
            if (array_out[0] != 0)
            {
                return -82;
            }

            return ret;
        }

        private int NT_Cal(Byte[] InBuf, Byte[] outbuf, string Path, int pos)
        {
            int n;
            Byte[] array_in = new Byte[257];
            Byte[] array_out = new Byte[257];


            array_in[1] = 8;
            for (n = 2; n <= 9; n++)
            {
                array_in[n] = InBuf[n - 2 + pos];
            }

            int ret = TransferData(array_in, 9, ref array_out, 9, Path);
            for (n = 0; n < 8; n++)
            {
                outbuf[n + pos] = array_out[n];
            }

            if (array_out[8] != 0x55)
            {
                return -20;
            }

            return ret;
        }

        private int NT_SetCal_2(Byte[] indata, Byte IsHi, string Path, short pos)
        {
            int n;
            Byte[] array_in = new Byte[257];
            Byte[] array_out = new Byte[257];


            array_in[1] = 9;
            array_in[2] = IsHi;
            for (n = 0; n < 8; n++)
            {
                array_in[3 + n] = indata[n + pos];
            }

            int ret = TransferData(array_in, 11, ref array_out, 2, Path);
            if (array_out[0] != 0)
            {
                return -82;
            }

            return ret;
        }

        private int ReadDword(ref int out_data, string Path)
        {
            Byte b1 = 0;
            Byte b2 = 0;
            Byte b3 = 0;
            Byte b4 = 0;
            int t1;
            int t2;
            int t3;
            int t4;
            int ret;
            ret = NT_Read(ref b1, ref b2, ref b3, ref b4, Path);
            t1 = b1;
            t2 = b2;
            t3 = b3;
            t4 = b4;
            out_data = t1 | (t2 << 8) | (t3 << 16) | (t4 << 24);
            return ret;
        }

        private int WriteDword(int in_data, string Path)
        {
            Byte b1;
            Byte b2;
            Byte b3;
            Byte b4;
            b1 = (Byte)(in_data & 255);
            b2 = (Byte)((in_data >> 8) & 255);
            b3 = (Byte)((in_data >> 16) & 255);
            b4 = (Byte)((in_data >> 24) & 255);
            return NT_Write(b1, b2, b3, b4, Path);
        }

        private int WriteDword_2(int in_data, string Path)
        {
            Byte b1;
            Byte b2;
            Byte b3;
            Byte b4;
            b1 = (Byte)(in_data & 255);
            b2 = (Byte)((in_data >> 8) & 255);
            b3 = (Byte)((in_data >> 16) & 255);
            b4 = (Byte)((in_data >> 24) & 255);
            return NT_Write_2(b1, b2, b3, b4, Path);
        }

        public int NT_GetIDVersion(ref short Version, string Path)
        {
            int ret;

            ret = GetIDVersion(ref Version, Path);

            return ret;
        }

        public int GetID(ref int ID_1, ref int ID_2, string Path)
        {
            int ret;

            ret = NT_GetID(ref ID_1, ref ID_2, Path);

            return ret;
        }

        public int sRead(ref int in_data, string Path)
        {
            int ret;

            ret = ReadDword(ref in_data, Path);

            return ret;
        }

        public int sWrite(int out_data, string Path)
        {
            int ret;

            ret = WriteDword(out_data, Path);

            return ret;
        }

        public int YWrite(Byte[] indata, int address, int nlen, string HKey, string LKey, string Path)
        {
            int ret = 0;

            Byte[] password = new Byte[8];
            int n, trashLen = 0;
            int leave;
            int temp_leave;
            if ((address + nlen - 1 > MAX_LEN) || (address < 0)) return -81;

            ret = GetTrashBufLen(Path, ref trashLen);
            if (trashLen < 100) trashLen = 16;
            trashLen = trashLen - 8;
            if (ret != 0) return ret;

            myconvert(HKey, LKey, password);

            temp_leave = address % trashLen;
            leave = trashLen - temp_leave;
            if (leave > nlen) leave = nlen;
            if (leave > 0)
            {
                for (n = 0; n < leave / trashLen; n++)
                {
                    ret = Y_Write(indata, address + n * trashLen, trashLen, password, Path, trashLen * n);
                    if (ret != 0)
                    {
                        return ret;
                    }
                }

                if (leave - trashLen * n > 0)
                {
                    ret = Y_Write(indata, address + n * trashLen, leave - n * trashLen, password, Path, trashLen * n);
                    if (ret != 0)
                    {
                        return ret;
                    }
                }
            }

            nlen = nlen - leave;
            address = address + leave;
            if (nlen > 0)
            {
                for (n = 0; n < nlen / trashLen; n++)
                {
                    ret = Y_Write(indata, address + n * trashLen, trashLen, password, Path, leave + trashLen * n);
                    if (ret != 0)
                    {
                        return ret;
                    }
                }

                if (nlen - trashLen * n > 0)
                {
                    ret = Y_Write(indata, address + n * trashLen, nlen - n * trashLen, password, Path,
                        leave + trashLen * n);
                    if (ret != 0)
                    {
                        return ret;
                    }
                }
            }

            return ret;
        }

        public int YRead(Byte[] OutData, short address, short nlen, string HKey, string LKey, string Path)
        {
            int ret = 0;

            Byte[] password = new Byte[8];
            int n, trashLen = 0;

            if ((address + nlen - 1 > MAX_LEN) || (address < 0)) return (-81);

            ret = GetTrashBufLen(Path, ref trashLen);
            if (trashLen < 100) trashLen = 16;
            if (ret != 0) return ret;


            myconvert(HKey, LKey, password);

            for (n = 0; n < nlen / trashLen; n++)
            {
                ret = Y_Read(OutData, address + n * trashLen, trashLen, password, Path, n * trashLen);
                if (ret != 0)
                {
                    return ret;
                }
            }

            if (nlen - trashLen * n > 0)
            {
                ret = Y_Read(OutData, address + n * trashLen, nlen - trashLen * n, password, Path, trashLen * n);
                if (ret != 0)
                {
                    return ret;
                }
            }

            return ret;
        }

        public int FindPort_2(int start, int in_data, int verf_data, ref string OutPath)
        {
            int ret;

            ret = NT_FindPort_2(start, in_data, verf_data, ref OutPath);

            return ret;
        }

        public int FindPort(int start, ref string OutPath)
        {
            int ret;

            ret = NT_FindPort(start, ref OutPath);

            return ret;
        }


        public int sWrite_2(int out_data, string Path)
        {
            int ret;

            ret = WriteDword_2(out_data, Path);

            return ret;
        }

        private string AddZero(string InKey)
        {
            int nlen;
            int n;
            nlen = InKey.Length;
            for (n = nlen; n <= 7; n++)
            {
                InKey = "0" + InKey;
            }

            return InKey;
        }

        private void myconvert(string HKey, string LKey, Byte[] out_data)
        {
            HKey = AddZero(HKey);
            LKey = AddZero(LKey);
            int n;
            for (n = 0; n <= 3; n++)
            {
                out_data[n] = (Byte)HexToInt(HKey.Substring(n * 2, 2));
            }

            for (n = 0; n <= 3; n++)
            {
                out_data[n + 4] = (Byte)HexToInt(LKey.Substring(n * 2, 2));
            }
        }

        public int SetReadPassword(string W_HKey, string W_LKey, string new_HKey, string new_LKey, string Path)
        {
            int ret;

            Byte[] ary1 = new Byte[8];
            Byte[] ary2 = new Byte[8];
            short address;
            myconvert(W_HKey, W_LKey, ary1);
            myconvert(new_HKey, new_LKey, ary2);
            address = 2032;


            ret = Y_Write(ary2, address, 8, ary1, Path, 0);


            return ret;
        }


        public int SetWritePassword(string W_HKey, string W_LKey, string new_HKey, string new_LKey, string Path)
        {
            int ret;

            Byte[] ary1 = new Byte[8];
            Byte[] ary2 = new Byte[8];
            short address;
            myconvert(W_HKey, W_LKey, ary1);
            myconvert(new_HKey, new_LKey, ary2);
            address = 2040;


            ret = Y_Write(ary2, address, 8, ary1, Path, 0);


            return ret;
        }

        public int YWriteString(string InString, int address, string HKey, string LKey, string Path)
        {
            int ret = 0;
            Byte[] ary1 = new Byte[8];

            int n, trashLen = 0;
            int outlen;
            int total_len;
            int temp_leave;
            int leave;
            Byte[] b;
            if ((address < 0)) return -81;

            ret = GetTrashBufLen(Path, ref trashLen);
            if (trashLen < 100) trashLen = 16;
            trashLen = trashLen - 8;
            if (ret != 0) return ret;

            myconvert(HKey, LKey, ary1);

            byte[] SrcbyteArray = System.Text.Encoding.Default.GetBytes(InString);
            outlen = SrcbyteArray.Length;
            b = new Byte[outlen];
            Array.Copy(SrcbyteArray, b, SrcbyteArray.Length);

            total_len = address + outlen;
            if (total_len > MAX_LEN) return -47;


            temp_leave = address % trashLen;
            leave = trashLen - temp_leave;
            if (leave > outlen) leave = outlen;

            if (leave > 0)
            {
                for (n = 0; n < (leave / trashLen); n++)
                {
                    ret = Y_Write(b, address + n * trashLen, trashLen, ary1, Path, n * trashLen);
                    if (ret != 0)
                    {
                        return ret;
                    }
                }

                if (leave - trashLen * n > 0)
                {
                    ret = Y_Write(b, address + n * trashLen, leave - n * trashLen, ary1, Path, trashLen * n);
                    if (ret != 0)
                    {
                        return ret;
                    }
                }
            }

            outlen = outlen - leave;
            address = address + leave;
            if (outlen > 0)
            {
                for (n = 0; n < (outlen / trashLen); n++)
                {
                    ret = Y_Write(b, address + n * trashLen, trashLen, ary1, Path, leave + n * trashLen);
                    if (ret != 0)
                    {
                        return ret;
                    }
                }

                if (outlen - trashLen * n > 0)
                {
                    ret = Y_Write(b, address + n * trashLen, outlen - n * trashLen, ary1, Path, leave + trashLen * n);
                    if (ret != 0)
                    {
                        return ret;
                    }
                }
            }


            return SrcbyteArray.Length;
        }

        public int YReadString(ref string OutString, int address, int nlen, string HKey, string LKey, string Path)
        {
            int ret = 0;
            Byte[] ary1 = new Byte[8];

            int n, trashLen = 0;
            int total_len;
            Byte[] outb;
            outb = new Byte[nlen];
            myconvert(HKey, LKey, ary1);
            if (address < 0) return -81;

            ret = GetTrashBufLen(Path, ref trashLen);
            if (trashLen < 100) trashLen = 16;
            if (ret != 0) return ret;

            total_len = address + nlen;
            if (total_len > MAX_LEN) return -47;


            for (n = 0; n < (nlen / trashLen); n++)
            {
                ret = Y_Read(outb, address + n * trashLen, trashLen, ary1, Path, n * trashLen);
                if (ret != 0)
                {
                    return ret;
                }
            }

            if (nlen - trashLen * n > 0)
            {
                ret = Y_Read(outb, address + n * trashLen, nlen - trashLen * n, ary1, Path, trashLen * n);
                if (ret != 0)
                {
                    return ret;
                }
            }

            OutString = ByteConvertString(outb);
            return ret;
        }

        public int SetCal_2(string Key, string Path)
        {
            int ret;

            Byte[] KeyBuf = new Byte[16];
            Byte[] inb = new Byte[8];
            HexStringToByteArray(Key, ref KeyBuf);


            ret = NT_SetCal_2(KeyBuf, 0, Path, 8);
            if (ret != 0) goto error1;
            ret = NT_SetCal_2(KeyBuf, 1, Path, 0);
            error1:


            return ret;
        }

        public int Cal(Byte[] InBuf, Byte[] outbuf, string Path)
        {
            int ret;


            ret = NT_Cal(InBuf, outbuf, Path, 0);


            return ret;
        }

        public int EncString(string InString, ref string OutString, string Path)
        {
            Byte[] b;
            Byte[] outb;
            int n;
            int nlen, temp_len;
            int ret = 0;
            byte[] SrcbyteArray = System.Text.Encoding.Default.GetBytes(InString);

            nlen = SrcbyteArray.Length + 1;
            temp_len = nlen;
            if (nlen < 8)
            {
                nlen = 8;
            }


            b = new Byte[nlen];
            outb = new Byte[nlen];

            Array.Copy(SrcbyteArray, b, SrcbyteArray.Length);

            b.CopyTo(outb, 0);


            for (n = 0; n <= (nlen - 8); n = n + 8)
            {
                ret = NT_Cal(b, outb, Path, n);
                if (ret != 0) break;
            }


            OutString = "";
            for (n = 0; n < nlen; n++)
            {
                OutString = OutString + outb[n].ToString("X2");
            }

            return ret;
        }

        public int sWriteEx(int in_data, ref int out_data, string Path)
        {
            int ret;


            ret = WriteDword(in_data, Path);
            if (ret != 0) goto error1;
            ret = ReadDword(ref out_data, Path);
            error1:


            return ret;
        }

        public int sWrite_2Ex(int in_data, ref int out_data, string Path)
        {
            int ret;


            ret = WriteDword_2(in_data, Path);
            if (ret != 0) goto error1;
            ret = ReadDword(ref out_data, Path);
            error1:


            return ret;
        }

        public int ReSet(string Path)
        {
            int ret;


            ret = NT_ReSet(Path);


            return ret;
        }

        private int NT_ReSet(string Path)
        {
            Byte[] array_in = new Byte[257];
            Byte[] array_out = new Byte[257];


            array_in[1] = 32;
            int ret = TransferData(array_in, 2, ref array_out, 2, Path);
            if (array_out[0] != 0)
            {
                return -82;
            }

            return ret;
        }

        public int SetCal_New(string Key, string Path)
        {
            int ret;

            Byte[] KeyBuf = new Byte[16];
            Byte[] inb = new Byte[8];
            HexStringToByteArray(Key, ref KeyBuf);


            ret = NT_SetCal_New(KeyBuf, 0, Path, 8);
            if (ret != 0) goto error1;
            ret = NT_SetCal_New(KeyBuf, 1, Path, 0);
            error1:


            return ret;
        }

        public int Cal_New(Byte[] InBuf, Byte[] outbuf, string Path)
        {
            int ret;


            ret = NT_Cal_New(InBuf, outbuf, Path, 0);


            return ret;
        }

        public int EncString_New(string InString, ref string OutString, string Path)
        {
            Byte[] b;
            Byte[] outb;
            int n;
            int nlen, temp_len;
            int ret = 0;
            byte[] SrcbyteArray = System.Text.Encoding.Default.GetBytes(InString);

            nlen = SrcbyteArray.Length + 1;

            temp_len = nlen;
            if (nlen < 8)
            {
                nlen = 8;
            }


            b = new Byte[nlen];
            outb = new Byte[nlen];

            Array.Copy(SrcbyteArray, b, SrcbyteArray.Length);

            b.CopyTo(outb, 0);


            for (n = 0; n <= (nlen - 8); n = n + 8)
            {
                ret = NT_Cal_New(b, outb, Path, n);
                if (ret != 0) break;
            }


            OutString = "";
            for (n = 0; n < nlen; n++)
            {
                OutString = OutString + outb[n].ToString("X2");
            }

            return ret;
        }

        public int NT_GetVersionEx(ref short Version, string Path)
        {
            int ret;


            ret = F_GetVersionEx(ref Version, Path);


            return ret;
        }

        private int NT_Cal_New(Byte[] InBuf, Byte[] outbuf, string Path, int pos)
        {
            int n;
            Byte[] array_in = new Byte[257];
            Byte[] array_out = new Byte[257];


            array_in[1] = 12;
            for (n = 2; n <= 9; n++)
            {
                array_in[n] = InBuf[n - 2 + pos];
            }

            int ret = TransferData(array_in, 9, ref array_out, 9, Path);
            for (n = 0; n < 8; n++)
            {
                outbuf[n + pos] = array_out[n];
            }

            if (array_out[8] != 0x55)
            {
                return -20;
            }

            return ret;
        }

        private int NT_SetCal_New(Byte[] indata, Byte IsHi, string Path, short pos)
        {
            int n;
            Byte[] array_in = new Byte[257];
            Byte[] array_out = new Byte[257];


            array_in[1] = 13;
            array_in[2] = IsHi;
            for (n = 0; n < 8; n++)
            {
                array_in[3 + n] = indata[n + pos];
            }

            int ret = TransferData(array_in, 11, ref array_out, 2, Path);
            if (array_out[0] != 0)
            {
                return -82;
            }

            return ret;
        }

        private int F_GetVersionEx(ref short Version, string Path)
        {
            Byte[] array_in = new Byte[257];
            Byte[] array_out = new Byte[257];


            array_in[1] = 5;
            int ret = TransferData(array_in, 1, ref array_out, 1, Path);
            Version = array_out[0];
            return ret;
        }


        public int SetHidOnly(bool IsHidOnly, string Path)
        {
            int ret;


            ret = NT_SetHidOnly(IsHidOnly, Path);


            return ret;
        }

        private int NT_SetHidOnly(bool IsHidOnly, string Path)
        {
            Byte[] array_in = new Byte[257];
            Byte[] array_out = new Byte[257];


            array_in[1] = 0x55;
            if (IsHidOnly) array_in[2] = 0;
            else array_in[2] = 0xff;
            int ret = TransferData(array_in, 3, ref array_out, 1, Path);
            if (array_out[0] != 0)
            {
                return -82;
            }

            return ret;
        }

        public int SetUReadOnly(string Path)
        {
            int ret;


            ret = NT_SetUReadOnly(Path);


            return ret;
        }

        private int NT_SetUReadOnly(string Path)
        {
            Byte[] array_in = new Byte[257];
            Byte[] array_out = new Byte[257];


            array_in[1] = 0x56;
            int ret = TransferData(array_in, 3, ref array_out, 1, Path);
            if (array_out[0] != 0)
            {
                return -82;
            }

            return ret;
        }

        private int sub_GetTrashBufLen(IntPtr hDevice, ref int out_len)
        {
            /* IntPtr Ppd = System.IntPtr.Zero;
             HIDP_CAPS Caps = new HIDP_CAPS();

             if (!HidD_GetPreparsedData(hDevice, ref Ppd)) return -93;

             if (HidP_GetCaps(Ppd, ref Caps) <= 0)
             {
                 HidD_FreePreparsedData(Ppd);
                 return -93;
             }
             HidD_FreePreparsedData(Ppd);
             out_len = Caps.FeatureReportByteLength - 5;*/
            return 0;
        }

        private int GetTrashBufLen(string Path, ref int out_len)
        {
            out_len = 16;
            return 0;
        }

        private int NT_Set_SM2_KeyPair(Byte[] PriKey, Byte[] PubKeyX, Byte[] PubKeyY, Byte[] sm2_UerName, string Path)
        {
            Byte[] array_in = new Byte[257];
            Byte[] array_out = new Byte[257];
            int n = 0;


            array_in[1] = 0x32;
            for (n = 0; n < ECC_MAXLEN; n++)
            {
                array_in[2 + n + ECC_MAXLEN * 0] = PriKey[n];
                array_in[2 + n + ECC_MAXLEN * 1] = PubKeyX[n];
                array_in[2 + n + ECC_MAXLEN * 2] = PubKeyY[n];
            }

            for (n = 0; n < SM2_USENAME_LEN; n++)
            {
                array_in[2 + n + ECC_MAXLEN * 3] = sm2_UerName[n];
            }

            int ret = TransferData(array_in, ECC_MAXLEN * 3 + SM2_USENAME_LEN + 2, ref array_out, 2, Path);
            if (array_out[0] != 0x20) return USBStatusFail;

            return ret;
        }

        private int NT_GenKeyPair(Byte[] PriKey, Byte[] PubKey, string Path)
        {
            Byte[] array_in = new Byte[257];
            Byte[] array_out = new Byte[257];
            int n = 0;
            array_out[0] = 0xfb;

            array_in[1] = GEN_KEYPAIR;

            int ret = TransferData(array_in, 2, ref array_out, ECC_MAXLEN * 3 + 2, Path);

            if (array_out[0] != 0x20)
            {
                return FAILEDGENKEYPAIR; //表示读取失败；
            }

            for (n = 0; n < ECC_MAXLEN; n++)
            {
                PriKey[n] = array_out[1 + ECC_MAXLEN * 0 + n];
            }

            for (n = 0; n < (ECC_MAXLEN * 2 + 1); n++)
            {
                PubKey[n] = array_out[1 + ECC_MAXLEN * 1 + n];
            }

            return ret;
        }

        private int NT_GetChipID(Byte[] OutChipID, string Path)
        {
            int[] t = new int[8];
            int n;
            Byte[] array_in = new Byte[257];
            Byte[] array_out = new Byte[257];


            array_in[1] = GET_CHIPID;
            int ret = TransferData(array_in, 1, ref array_out, 17, Path);
            if (array_out[0] != 0x20) return USBStatusFail;
            for (n = 0; n < 16; n++)
            {
                OutChipID[n] = array_out[1 + n];
            }

            return ret;
        }


        private int NT_Get_SM2_PubKey(Byte[] KGx, Byte[] KGy, Byte[] sm2_UerName, string Path)
        {
            Byte[] array_in = new Byte[257];
            Byte[] array_out = new Byte[257];
            int n = 0;


            array_in[1] = 0x33;
            int ret = TransferData(array_in, 2, ref array_out, ECC_MAXLEN * 2 + SM2_USENAME_LEN + 2, Path);
            if (array_out[0] != 0x20) return USBStatusFail;

            for (n = 0; n < ECC_MAXLEN; n++)
            {
                KGx[n] = array_out[1 + ECC_MAXLEN * 0 + n];
                KGy[n] = array_out[1 + ECC_MAXLEN * 1 + n];
            }

            for (n = 0; n < SM2_USENAME_LEN; n++)
            {
                sm2_UerName[n] = array_out[1 + ECC_MAXLEN * 2 + n];
            }

            return ret;
        }

        private int NT_Set_Pin(string old_pin, string new_pin, string Path)
        {
            Byte[] array_in = new Byte[257];
            Byte[] array_out = new Byte[257];
            int n = 0;


            array_in[1] = SET_PIN;
            Byte[] b_oldpin = System.Text.Encoding.Default.GetBytes(old_pin);

            Byte[] b_newpin = System.Text.Encoding.Default.GetBytes(new_pin);

            for (n = 0; n < PIN_LEN; n++)
            {
                array_in[2 + PIN_LEN * 0 + n] = b_oldpin[n];
                array_in[2 + PIN_LEN * 1 + n] = b_newpin[n];
            }

            int ret = TransferData(array_in, PIN_LEN * 2 + 2, ref array_out, 2, Path);
            if (array_out[0] != 0x20) return USBStatusFail;
            if (array_out[1] != 0x20) return FAILPINPWD;
            return ret;
        }


        private int NT_SM2_Enc(Byte[] inbuf, Byte[] outbuf, Byte inlen, string Path)
        {
            Byte[] array_in = new Byte[257];
            Byte[] array_out = new Byte[257];
            int n = 0;


            array_in[1] = MYENC;
            array_in[2] = inlen;
            for (n = 0; n < inlen; n++)
            {
                array_in[3 + n] = inbuf[n];
            }

            int ret = TransferData(array_in, inlen + 1 + 2, ref array_out, inlen + SM2_ADDBYTE + 3, Path);
            if (array_out[0] != 0x20) return USBStatusFail;
            if (array_out[1] == 0) return FAILENC;

            for (n = 0; n < (inlen + SM2_ADDBYTE); n++)
            {
                outbuf[n] = array_out[2 + n];
            }

            return ret;
        }

        private int NT_SM2_Dec(Byte[] inbuf, Byte[] outbuf, Byte inlen, string pin, string Path)
        {
            Byte[] array_in = new Byte[257];
            Byte[] array_out = new Byte[257];
            int n = 0;


            array_in[1] = MYDEC;
            Byte[] b_pin = System.Text.Encoding.Default.GetBytes(pin);

            for (n = 0; n < PIN_LEN; n++)
            {
                array_in[2 + PIN_LEN * 0 + n] = b_pin[n];
            }

            array_in[2 + PIN_LEN] = inlen;
            for (n = 0; n < inlen; n++)
            {
                array_in[2 + PIN_LEN + 1 + n] = inbuf[n];
            }

            int ret = TransferData(array_in, inlen + 1 + 2 + PIN_LEN, ref array_out, inlen - SM2_ADDBYTE + 4, Path);
            if (array_out[2] != 0x20) return FAILPINPWD;
            if (array_out[1] == 0) return FAILENC;
            if (array_out[0] != 0x20) return USBStatusFail;
            for (n = 0; n < (inlen - SM2_ADDBYTE); n++)
            {
                outbuf[n] = array_out[3 + n];
            }

            return ret;
        }

        private int NT_Sign(Byte[] inbuf, Byte[] outbuf, string pin, string Path)
        {
            Byte[] array_in = new Byte[257];
            Byte[] array_out = new Byte[257];
            int n = 0;


            array_in[1] = YTSIGN;
            Byte[] b_pin = System.Text.Encoding.Default.GetBytes(pin);

            for (n = 0; n < PIN_LEN; n++)
            {
                array_in[2 + PIN_LEN * 0 + n] = b_pin[n];
            }

            for (n = 0; n < 32; n++)
            {
                array_in[2 + PIN_LEN + n] = inbuf[n];
            }

            int ret = TransferData(array_in, 32 + 2 + PIN_LEN, ref array_out, 64 + 3, Path);
            if (array_out[1] != 0x20) return FAILPINPWD;
            if (array_out[0] != 0x20) return USBStatusFail;
            for (n = 0; n < 64; n++)
            {
                outbuf[n] = array_out[2 + n];
            }

            return ret;
        }

        private int NT_Sign_2(Byte[] inbuf, Byte[] outbuf, string pin, string Path)
        {
            Byte[] array_in = new Byte[257];
            Byte[] array_out = new Byte[257];
            int n = 0;


            array_in[1] = YTSIGN_2;
            Byte[] b_pin = System.Text.Encoding.Default.GetBytes(pin);

            for (n = 0; n < PIN_LEN; n++)
            {
                array_in[2 + PIN_LEN * 0 + n] = b_pin[n];
            }

            for (n = 0; n < 32; n++)
            {
                array_in[2 + PIN_LEN + n] = inbuf[n];
            }

            int ret = TransferData(array_in, 32 + 2 + PIN_LEN, ref array_out, 64 + 3, Path);
            if (array_out[1] != 0x20) return FAILPINPWD;
            if (array_out[0] != 0x20) return USBStatusFail;
            for (n = 0; n < 64; n++)
            {
                outbuf[n] = array_out[2 + n];
            }

            return ret;
        }


        private int NT_Verfiy(Byte[] inbuf, Byte[] InSignBuf, ref bool outbiao, string Path)
        {
            Byte[] array_in = new Byte[257];
            Byte[] array_out = new Byte[257];
            int n = 0;


            array_in[1] = YTVERIFY;
            for (n = 0; n < 32; n++)
            {
                array_in[2 + n] = inbuf[n];
            }

            for (n = 0; n < 64; n++)
            {
                array_in[2 + 32 + n] = InSignBuf[n];
            }

            int ret = TransferData(array_in, 32 + 2 + 64, ref array_out, 3, Path);
            outbiao = (array_out[1] != 0);
            if (array_out[0] != 0x20) return USBStatusFail;

            return ret;
        }

        private string ByteArrayToHexString(Byte[] in_data, int nlen)
        {
            return ByteArrayToHexStringEx(in_data, nlen, 0);
        }

        private string ByteArrayToHexStringEx(Byte[] in_data, int nlen, int pos)
        {
            string OutString = "";
            int n;
            for (n = 0; n < nlen; n++)
            {
                OutString = OutString + in_data[n + pos].ToString("X2");
            }

            return OutString;
        }

        public int YT_GenKeyPair(ref string PriKey, ref string PubKeyX, ref string PubKeyY, string InPath)
        {
            int ret, n;
            Byte[] b_PriKey = new Byte[ECC_MAXLEN], b_PubKey = new Byte[ECC_MAXLEN * 2 + 1]; //其中第一个字节是标志位，忽略


            ret = NT_GenKeyPair(b_PriKey, b_PubKey, InPath);


            PriKey = ByteArrayToHexString(b_PriKey, ECC_MAXLEN);
            PubKeyX = "";
            PubKeyY = "";
            for (n = 0; n < ECC_MAXLEN; n++)
            {
                PubKeyX = PubKeyX + b_PubKey[n + 1].ToString("X2");
                PubKeyY = PubKeyY + b_PubKey[n + 1 + ECC_MAXLEN].ToString("X2");
            }

            return ret;
        }

        public int Set_SM2_KeyPair(string PriKey, string PubKeyX, string PubKeyY, string SM2_UserName, string InPath)
        {
            int ret;
            Byte[] b_PriKey = new Byte[ECC_MAXLEN], b_PubKeyX = new Byte[ECC_MAXLEN], b_PubKeyY = new Byte[ECC_MAXLEN];
            HexStringToByteArray(PriKey, ref b_PriKey);
            HexStringToByteArray(PubKeyX, ref b_PubKeyX);
            HexStringToByteArray(PubKeyY, ref b_PubKeyY);

            Byte[] b_SM2UserName = System.Text.Encoding.Default.GetBytes(SM2_UserName);

            ret = NT_Set_SM2_KeyPair(b_PriKey, b_PubKeyX, b_PubKeyY, b_SM2UserName, InPath);


            return ret;
        }

        public int Get_SM2_PubKey(ref string PubKeyX, ref string PubKeyY, ref string sm2UserName, string InPath)
        {
            int ret;
            Byte[] b_PubKeyX = new Byte[ECC_MAXLEN],
                b_PubKeyY = new Byte[ECC_MAXLEN],
                b_sm2UserName = new Byte[SM2_USENAME_LEN];


            ret = NT_Get_SM2_PubKey(b_PubKeyX, b_PubKeyY, b_sm2UserName, InPath);


            PubKeyX = ByteArrayToHexString(b_PubKeyX, ECC_MAXLEN);
            PubKeyY = ByteArrayToHexString(b_PubKeyY, ECC_MAXLEN);


            sm2UserName = ByteConvertString(b_sm2UserName);
            return ret;
        }

        public int GetChipID(ref string OutChipID, string InPath)
        {
            int ret;
            Byte[] b_OutChipID = new Byte[16];

            ret = NT_GetChipID(b_OutChipID, InPath);


            OutChipID = ByteArrayToHexString(b_OutChipID, 16);
            return ret;
        }

        public int SM2_EncBuf(Byte[] InBuf, Byte[] OutBuf, int inlen, string InPath)
        {
            int ret = 0, n, temp_inlen, incount = 0, outcount = 0;
            Byte[] temp_InBuf = new Byte[MAX_ENCLEN + SM2_ADDBYTE], temp_OutBuf = new Byte[MAX_ENCLEN + SM2_ADDBYTE];
            while (inlen > 0)
            {
                if (inlen > MAX_ENCLEN)
                    temp_inlen = MAX_ENCLEN;
                else
                    temp_inlen = inlen;
                for (n = 0; n < temp_inlen; n++)
                {
                    temp_InBuf[n] = InBuf[incount + n];
                }

                ret = NT_SM2_Enc(temp_InBuf, temp_OutBuf, (Byte)temp_inlen, InPath);
                for (n = 0; n < (temp_inlen + SM2_ADDBYTE); n++)
                {
                    OutBuf[outcount + n] = temp_OutBuf[n];
                }

                if (ret != 0) goto err;
                inlen = inlen - MAX_ENCLEN;
                incount = incount + MAX_ENCLEN;
                outcount = outcount + MAX_DECLEN;
            }

            err:


            return ret;
        }

        public int SM2_DecBuf(Byte[] InBuf, Byte[] OutBuf, int inlen, string pin, string InPath)
        {
            int ret = 0, temp_inlen, n, incount = 0, outcount = 0;
            Byte[] temp_InBuf = new Byte[MAX_ENCLEN + SM2_ADDBYTE], temp_OutBuf = new Byte[MAX_ENCLEN + SM2_ADDBYTE];

            while (inlen > 0)
            {
                if (inlen > MAX_DECLEN)
                    temp_inlen = MAX_DECLEN;
                else
                    temp_inlen = inlen;
                for (n = 0; n < temp_inlen; n++)
                {
                    temp_InBuf[n] = InBuf[incount + n];
                }

                ret = NT_SM2_Dec(InBuf, OutBuf, (Byte)temp_inlen, pin, InPath);
                for (n = 0; n < (temp_inlen - SM2_ADDBYTE); n++)
                {
                    OutBuf[outcount + n] = temp_OutBuf[n];
                }

                if (ret != 0) goto err;
                inlen = inlen - MAX_DECLEN;
                incount = incount + MAX_DECLEN;
                outcount = outcount + MAX_ENCLEN;
            }

            err:


            return ret;
        }

        public int SM2_EncString(string InString, ref string OutString, string InPath)
        {
            int n, incount = 0, outcount = 0;
            Byte[] temp_InBuf = new Byte[MAX_ENCLEN + SM2_ADDBYTE], temp_OutBuf = new Byte[MAX_ENCLEN + SM2_ADDBYTE];
            byte[] SrcbyteArray = System.Text.Encoding.Default.GetBytes(InString);

            int inlen = SrcbyteArray.Length + 1;
            int outlen = (int)Math.Ceiling((double)inlen / (MAX_ENCLEN)) * SM2_ADDBYTE + inlen;
            Byte[] OutBuf = new Byte[outlen];
            Byte[] InBuf = new Byte[inlen];
            Array.Copy(SrcbyteArray, InBuf, SrcbyteArray.Length);
            int ret = 0, temp_inlen;

            while (inlen > 0)
            {
                if (inlen > MAX_ENCLEN)
                    temp_inlen = MAX_ENCLEN;
                else
                    temp_inlen = inlen;
                for (n = 0; n < temp_inlen; n++)
                {
                    temp_InBuf[n] = InBuf[incount + n];
                }

                ret = NT_SM2_Enc(temp_InBuf, temp_OutBuf, (Byte)temp_inlen, InPath);
                for (n = 0; n < (temp_inlen + SM2_ADDBYTE); n++)
                {
                    OutBuf[outcount + n] = temp_OutBuf[n];
                }

                if (ret != 0) goto err;
                inlen = inlen - MAX_ENCLEN;
                incount = incount + MAX_ENCLEN;
                outcount = outcount + MAX_DECLEN;
            }

            err:
            OutString = ByteArrayToHexString(OutBuf, outlen);


            return ret;
        }

        public int SM2_DecString(string InString, ref string OutString, string pin, string InPath)
        {
            int n, incount = 0, outcount = 0;
            Byte[] temp_InBuf = new Byte[MAX_ENCLEN + SM2_ADDBYTE], temp_OutBuf = new Byte[MAX_ENCLEN + SM2_ADDBYTE];
            byte[] SrcbyteArray = System.Text.Encoding.Default.GetBytes(InString);

            int inlen = SrcbyteArray.Length / 2;
            int outlen = inlen - (int)Math.Ceiling((double)inlen / (MAX_DECLEN)) * SM2_ADDBYTE + 1;
            Byte[] InBuf = new Byte[inlen];
            Byte[] OutBuf = new Byte[outlen];
            int ret = 0, temp_inlen;
            HexStringToByteArray(InString, ref InBuf);

            while (inlen > 0)
            {
                if (inlen > MAX_DECLEN)
                    temp_inlen = MAX_DECLEN;
                else
                    temp_inlen = inlen;
                for (n = 0; n < temp_inlen; n++)
                {
                    temp_InBuf[n] = InBuf[incount + n];
                }

                ret = NT_SM2_Dec(temp_InBuf, temp_OutBuf, (Byte)temp_inlen, pin, InPath);
                for (n = 0; n < (temp_inlen - SM2_ADDBYTE); n++)
                {
                    OutBuf[outcount + n] = temp_OutBuf[n];
                }

                if (ret != 0) goto err;
                inlen = inlen - MAX_DECLEN;
                incount = incount + MAX_DECLEN;
                outcount = outcount + MAX_ENCLEN;
            }

            err:


            OutString = ByteConvertString(OutBuf);
            return ret;
        }


        public int YtSetPin(string old_pin, string new_pin, string InPath)
        {
            int ret;


            ret = NT_Set_Pin(old_pin, new_pin, InPath);


            return ret;
        }

        private int NT_SetID(Byte[] InBuf, string Path)
        {
            int n;
            Byte[] array_in = new Byte[257];
            Byte[] array_out = new Byte[257];


            array_in[1] = 7;
            for (n = 2; n <= 9; n++)
            {
                array_in[n] = InBuf[n - 2];
            }

            int ret = TransferData(array_in, 9, ref array_out, 9, Path);
            if (array_out[0] != 0x0)
            {
                return -82;
            }

            return ret;
        }

        public int SetID(string Seed, string Path)
        {
            int ret;

            int n;
            Byte[] KeyBuf = new Byte[8];
            for (n = 0; n < 8; n++)
            {
                KeyBuf[n] = 0;
            }

            HexStringToByteArray(Seed, ref KeyBuf);


            ret = NT_SetID(KeyBuf, Path);


            return ret;
        }

        private int NT_GetProduceDate(ref string OutDate, string Path)
        {
            int n;
            Byte[] array_in = new Byte[257];
            Byte[] array_out = new Byte[257];


            array_in[1] = 15;

            int ret = TransferData(array_in, 1, ref array_out, 8, Path);
            OutDate = "";
            for (n = 0; n < 8; n++)
            {
                OutDate = OutDate + array_out[n].ToString("X2");
            }

            return ret;
        }

        //返回锁的出厂编码
        public int GetProduceDate(ref string PDate, string Path)
        {
            int ret;


            ret = NT_GetProduceDate(ref PDate, Path);


            return ret;
        }

        public string SnToProduceDate(string InSn)
        {
            string OutString;
            OutString = (2000 + HexToInt(InSn.Substring(0, 2))).ToString() + "年";
            OutString = OutString + (HexToInt(InSn.Substring(2, 2))).ToString() + "月";
            OutString = OutString + (HexToInt(InSn.Substring(4, 2))).ToString() + "日";
            OutString = OutString + (HexToInt(InSn.Substring(6, 2))).ToString() + "时";
            OutString = OutString + (HexToInt(InSn.Substring(8, 2))).ToString() + "分";
            OutString = OutString + (HexToInt(InSn.Substring(10, 2))).ToString() + "秒--";
            OutString = OutString + "序号：" + HexToInt(InSn.Substring(12, 4)).ToString();
            return OutString;
        }

        private int y_setcal(Byte[] indata, int address, int nlen, Byte[] password, string Path)
        {
            int n;
            Byte[] array_in = new Byte[257];
            Byte[] array_out = new Byte[257];

            if (nlen > 8) return -87;


            array_in[1] = 6;
            array_in[2] = 0;
            array_in[3] = 0;
            array_in[4] = (Byte)nlen;
            for (n = 0; n <= 7; n++)
            {
                array_in[5 + n] = password[n];
            }

            for (n = 0; n < nlen; n++)
            {
                array_in[13 + n] = indata[n];
            }

            int ret = TransferData(array_in, 13 + nlen, ref array_out, 2, Path);
            if (array_out[0] != 0)
            {
                return -82;
            }

            return ret;
        }

        public int SetCal(string W_HKey, string W_LKey, string new_HKey, string new_LKey, string Path)
        {
            int ret;

            Byte[] ary1 = new Byte[8];
            Byte[] ary2 = new Byte[8];
            short address;
            myconvert(W_HKey, W_LKey, ary1);
            myconvert(new_HKey, new_LKey, ary2);
            address = 0;


            ret = y_setcal(ary2, address, 8, ary1, Path);


            return ret;
        }

        private int NT_SetDisableFlag(Byte Flag, Byte[] password, string Path)
        {
            int n;
            Byte[] array_in = new Byte[257];
            Byte[] array_out = new Byte[257];


            array_in[1] = 0x40;
            array_in[2] = 0;
            array_in[3] = 0;
            array_in[4] = 1;
            for (n = 0; n <= 7; n++)
            {
                array_in[5 + n] = password[n];
            }

            array_in[13] = Flag;
            int ret = TransferData(array_in, 13 + 1, ref array_out, 2, Path);
            if (array_out[0] != 0)
            {
                return -82;
            }

            return ret;
        }

        private int NT_GetDisableFlag(ref bool isDisableFlag, string Path)
        {
            isDisableFlag = false;
            Byte[] array_in = new Byte[257];
            Byte[] array_out = new Byte[257];


            array_in[1] = 0x41;
            int ret = TransferData(array_in, 1, ref array_out, 2, Path);
            if (array_out[0] != 0)
            {
                return -82;
            }

            if (array_out[1] == 0xe5) isDisableFlag = true;
            return ret;
        }

        public int SetDisableFlag(bool isDisableFlag, string HKey, string LKey, string Path)
        {
            int ret;
            Byte Flag = 0;
            Byte[] ary = new Byte[8];
            myconvert(HKey, LKey, ary);
            if (isDisableFlag) Flag = 0xE5;


            ret = NT_SetDisableFlag(Flag, ary, Path);


            return ret;
        }

        public int GetDisableFlag(ref bool isDisableFlag, string Path)
        {
            int ret;


            ret = NT_GetDisableFlag(ref isDisableFlag, Path);


            return ret;
        }


        public void memset(Byte[] buf, int pos, Byte val, int size)
        {
            int n;
            for (n = pos; n < size; n++)
            {
                buf[n] = val;
            }
        }

        private int HanldetransferEx(Byte[] InBuf, int InBufLen, Byte[] OutBuf, int OutBufLen, string Path)
        {
            Byte[] t_InBuf = new byte[MAX_BUF_SIZE + 2];
            Byte[] t_OutBuf = new byte[MAX_BUF_SIZE + 2];
            Array.Copy(InBuf, 0, t_InBuf, 0, InBufLen + 1);
            int ret = TransferData(t_InBuf, InBufLen, ref t_OutBuf, OutBufLen, Path);
            if (ret != 0) return ret;
            Array.Copy(t_OutBuf, 0, OutBuf, 0, OutBufLen);
            ret = BitConverter.ToInt16(OutBuf, 0);
            return ret;
        }

        public int CheckKeyByFindort_2()
        {
            //使用普通算法一查找指定的加密锁
            string DevicePath = ""; //用于储存加密锁所在的路径
            return FindPort_2(0, 1, 16711934, ref DevicePath);
        }

        public int CheckKeyByFindort_3()
        {
            //使用普通算法二查找指定的加密锁
            string DevicePath = ""; //用于储存加密锁所在的路径
            //@NoUseCode_FindPort_3 return 2;//如果这个锁不支持这个功能，直接返回2
            return 2;
            //return FindPort_3(0, 1, 16711934, ref DevicePath);
        }

        //使用带长度的方法从指定的地址读取字符串
        public int ReadStringEx(int addr, ref string outstring, string DevicePath)
        {
            int nlen, ret;
            byte[] buf = new byte[1];
            //先从地址0读到以前写入的字符串的长度
            ret = YRead(buf, (short)addr, (short)1, "E1930089", "C7326137", DevicePath);
            if (ret != 0) return ret;
            nlen = buf[0];
            //再读取相应长度的字符串
            return YReadString(ref outstring, addr + 1, nlen, "E1930089", "C7326137", DevicePath);
        }

        //使用从储存器读取相应数据的方式检查是否存在指定的加密锁
        public int CheckKeyByReadEprom()
        {
            int n, ret;
            string DevicePath = ""; //用于储存加密锁所在的路径
            string outstring = "";
            return 1; //如果没有使用这个功能，直接返回1
            for (n = 0; n < 255; n++)
            {
                ret = FindPort(n, ref DevicePath);
                if (ret != 0) return ret;
                ret = ReadStringEx(0, ref outstring, DevicePath);
                if ((ret == 0) && (outstring.CompareTo("") == 0)) return 0;
            }

            return -92;
        }

        //使用增强算法一检查加密锁，这个方法可以有效地防止仿真
        public int CheckKeyByEncstring()
        {
            //推荐加密方案：生成随机数，让锁做加密运算，同时在程序中端使用代码做同样的加密运算，然后进行比较判断。

            int n, ret;
            string DevicePath = ""; //用于储存加密锁所在的路径
            string InString;

            //@NoUseKeyEx return 1;//如果没有使用这个功能，直接返回1
            System.Random rnd = new System.Random();

            InString = rnd.Next(0, 32767).ToString("X") + rnd.Next(0, 32767).ToString("X");

            for (n = 0; n < 255; n++)
            {
                ret = FindPort(n, ref DevicePath);
                if (ret != 0) return ret;
                if (Sub_CheckKeyByEncstring(InString, DevicePath) == 0) return 0;
            }

            return -92;
        }

        private int Sub_CheckKeyByEncstring(string InString, string DevicePath)
        {
            //使用增强算法一对字符串进行加密
            int ret;
            string outstring = "";
            string outstring_2;
            ret = EncString(InString, ref outstring, DevicePath);
            if (ret != 0) return ret;
            outstring_2 = StrEnc(InString, "389217D0F16CB88A512E734C70DB4F8E");
            if (outstring_2.CompareTo(outstring) == 0) //比较结果是否相符
            {
                ret = 0;
            }
            else
            {
                ret = -92;
            }

            return ret;
        }

        //使用增强算法二检查是否存在对应的加密锁
        public int CheckKeyByEncstring_New()
        {
            int n, ret;
            string DevicePath = ""; //用于储存加密锁所在的路径
            string outstring = "";
            System.Random rnd = new System.Random();
            int myrnd = rnd.Next(0, 500);
            String[] EncInString =
            {
                "10553", "19783", "19946", "15766", "29138", "17249", "7140", "25299", "29856", "864", "8881", "6675",
                "3053", "9827", "7918", "5508", "26913", "16430", "23892", "22265", "20167", "12580", "17597", "4582",
                "27273", "6212", "36", "11611", "20274", "25906",
                "18593", "26122", "3756", "2608", "20335", "4168", "29694", "19999", "18409", "31234", "23893", "16003",
                "4488", "27853", "13818", "16763", "486", "20444", "4184", "18379", "20157", "27135", "24566", "7894",
                "6119", "17320", "21378", "25243", "4447", "10475",
                "20164", "4031", "19773", "19319", "1190", "13697", "9660", "1185", "12593", "18373", "18231", "14169",
                "29585", "4366", "23078", "21041", "18447", "17531", "19749", "29020", "8726", "12241", "16110", "8365",
                "9774", "3440", "2137", "15763", "1027", "30298",
                "26209", "31010", "28765", "29746", "17440", "31243", "16168", "13114", "9425", "7843", "7533", "21587",
                "11725", "24279", "27477", "24320", "20621", "20029", "13869", "21347", "5294", "15877", "21084",
                "23613", "487", "32514", "5486", "8434", "10771", "17318",
                "12299", "14209", "21292", "8706", "10239", "13966", "16716", "13769", "29234", "26459", "8366",
                "25164", "11440", "6090", "4011", "13438", "30881", "3164", "18620", "25840", "29778", "4660", "27773",
                "31189", "21802", "12563", "27559", "2304", "8629", "32091",
                "4373", "6624", "2971", "2577", "11199", "10121", "27047", "31442", "22720", "17069", "20932", "13796",
                "27986", "21405", "21243", "13864", "209", "31820", "20342", "32030", "5811", "6732", "30335", "9452",
                "26773", "26830", "24192", "4688", "20528", "17061",
                "16132", "18094", "20830", "1091", "19123", "20999", "17433", "3513", "10585", "25854", "7804", "25785",
                "4575", "726", "24255", "30359", "1103", "21358", "5438", "31298", "9171", "5450", "3698", "29263",
                "12469", "12172", "7413", "20207", "8799", "25589",
                "897", "12275", "24923", "8424", "32496", "18125", "8532", "29542", "28732", "22672", "23314", "6419",
                "9856", "24558", "26241", "12846", "18676", "20280", "13482", "5020", "24820", "29281", "10679",
                "14557", "1017", "28923", "5874", "22035", "7581", "28727",
                "21701", "2562", "22937", "21736", "31930", "12298", "11722", "9600", "17276", "21037", "1064", "3088",
                "29395", "15119", "1228", "30794", "940", "10224", "32753", "24962", "22541", "6834", "30705", "10408",
                "5411", "19416", "19271", "6735", "7480", "15492",
                "32396", "4264", "10676", "26743", "9851", "13702", "1314", "6164", "29163", "25690", "25900", "21084",
                "21466", "11320", "25757", "28402", "19807", "29135", "7518", "18456", "22454", "12660", "25208",
                "3248", "28215", "24854", "6680", "12859", "14430", "29258",
                "14213", "1756", "21444", "29760", "21802", "25428", "15907", "21963", "28305", "32005", "24405",
                "18269", "14949", "22515", "13141", "15623", "9326", "22719", "5180", "4220", "26520", "30377", "9283",
                "17165", "18412", "3478", "22469", "24493", "27795", "20486",
                "7997", "31981", "23002", "22812", "12612", "24321", "2857", "24217", "29844", "14777", "11529", "737",
                "2568", "4744", "30500", "18163", "30359", "17023", "9800", "7283", "27999", "6225", "5723", "6051",
                "14744", "6735", "31847", "16740", "18587", "26731",
                "16536", "2362", "21476", "15929", "30775", "22340", "11020", "5354", "32686", "15942", "7629", "25934",
                "13448", "19874", "1538", "2522", "20333", "858", "29090", "16542", "24105", "24079", "27850", "19789",
                "23972", "3844", "27572", "15160", "29674", "19482",
                "21689", "16210", "18980", "16852", "10835", "14893", "1693", "9556", "21788", "23034", "26300",
                "26203", "3534", "23692", "30991", "333", "26435", "29012", "30525", "28968", "30837", "15206", "16402",
                "16787", "9855", "29553", "29046", "16589", "3738", "10698",
                "8822", "20920", "4127", "10337", "15673", "24023", "30345", "29896", "30985", "26444", "17268",
                "29234", "29779", "15064", "6295", "9074", "28318", "16862", "16845", "3320", "8854", "29791", "24336",
                "14037", "16387", "27391", "11899", "20158", "1490", "4350",
                "30278", "27139", "31753", "30270", "3789", "26519", "19925", "16706", "3209", "29196", "17279",
                "16684", "2580", "8596", "23665", "8126", "4648", "15871", "2358", "13144", "10655", "8386", "1399",
                "28926", "31090", "14061", "20989", "32339", "6335", "9011",
                "20147", "25495", "30394", "32741", "29860", "23980", "25794", "16630", "12281", "20501", "16463",
                "13816", "23036", "22260", "15611", "11292", "21272", "30986", "20096", "12341"
            };
            String[] EncOutString =
            {
                "C1E62AA68D77F26C", "382473C34EAFCB90", "9046D801EBC6F987", "FA693CD753862224", "28E488C974B183F5",
                "A236C8056BC74311", "12DE5A5D0A37E0BB", "7D4B973873D32A7E", "0712AFC4E796F724", "D7773040D01D0B52",
                "776ADB90595F0407", "FC5E71B4F5D911E1", "6F035CA0D25DE983", "66A85CFE63FD3BBE", "66E583FBEFBC92B6",
                "D5574F80CF6E9410", "E22699779F27BE0C", "6187E40A7EB277F6", "BC93CBC18B89D9BB", "F5F054BBEC12575E",
                "C3794A7771F66A40", "17023D941AD4866A", "B03FC0DA94DFD1AC", "8785CF1D1667F073", "B95DF7A5821286D4",
                "AE8E7B0E9045BACF", "5DB74AB530197B8A", "7668E2D871451EA2", "B6E17097428202A5", "959599240234F50C",
                "06E5577C18519D22", "D81CFCA41339C658", "95E3C76D2AA0B89A", "223775F6400C09E4", "170FEC2DF4A53B21",
                "CB6F2FB44E5CC3A5", "188D7C3E77E1E8F0", "6565E19FA93DC971", "898476103159C69F", "BE2E067CFF145CA9",
                "9C08447205F853B6", "4DEFED252CF6C824", "2695F0B4DA7E83A5", "2350B70EFA87390F", "603DD571FB0D9549",
                "B08D94399039920F", "4B3F27F00D5598F8", "F75C4EC69BAAE07B", "AB4A41272F043447", "051B199E1F61F0E7",
                "638F42AE37FB04D1", "9DB172A9138C7FA6", "EF325430E9CD17EF", "34C8A3B8463B0C99", "E475B479998265E7",
                "664005AE2C7E2536", "8B1A5F87434C712F", "AD6DD3ECAD35ED6D", "1FB00CF2E1D02AF5", "9AA185A2299C5DD0",
                "3776A6A5134B7F14", "BA55E5BF66E5B14E", "E65824033AE1E6DF", "FA7176107DC7924C", "D348B34E2BB64CDE",
                "DE7B1049DFFEC1C0", "0CE41D0233218EA8", "1D69487327859BD1", "83E4279C9D4E1388", "CA51085554E8FE2D",
                "AB87E5F7633985C2", "FCD8B2EDAEE6E8AA", "A5318D85DCABF24C", "658644BBBAEE42D0", "0573EC6BD7F019E3",
                "5C8B106A7769A6BB", "EA2A24F53CD57BF7", "7B019D9C62E6DF45", "DCCCE86016BC412C", "78B7AC961D4A35F3",
                "655207DC6D85CB03", "71446A24B87896BF", "C865B9ABF4E3D4E7", "52BA4883758F0B17", "F2B8DD8547C74872",
                "82C05F46DFD80CA8", "AA14A081C3CE1A37", "51C7D0922697C864", "36C2EAAE3539CBD6", "4C40005B44F82538",
                "BF546F66114AFA1A", "2F823EC453F4C717", "9565F8F155EFBCDA", "2007A053C5013AF6", "A8624A400C05D5BA",
                "BC1CC0A1BFA1F0DA", "6A9E8DFF9EE95967", "34E2AFD6AD845052", "F30206A8F05651FF", "D7249CCA67FDA77C",
                "EAA7AACF0906355F", "1948FB636AD0B240", "F5B77831170E279C", "BF9D5EA9FFC56895", "3116EEC8A0FB0B46",
                "31D677ECA624375C", "E26CC8EBAB5F2D34", "7532C7424FA1B6D2", "8179159D7AA6EECB", "70DF923D88618F1A",
                "29EEEEAF541CE27D", "5BE2A73E011E6C7A", "D7AE78369D0EF293", "89B641BB3E44A2C4", "3B166ECFFF78E313",
                "E757430C97ABED2D", "DBFC50731B1A350C", "91AF88D11AC39C09", "FC564F75D2B30B3D", "1D0DAF06B919FC31",
                "937F583EAD80D3D4", "C6840C5D73A81C4C", "B2FB75B17BA7BB8D", "E852018DCC07F8FA", "CDEEB7BE769F818A",
                "7AC0779CCD5B52AD", "D901C86680973AD6", "466FE65AA996EAAF", "32761ECFE13FCBE6", "B5D4D1D066AC420C",
                "D8B87FEA2FDD97B4", "72BA756CA6E7FD76", "F8793140D31FEB92", "5C78364299061112", "7AAABBFE4960B3F0",
                "75D095F945A7DBB8", "9C0B76404D58273F", "B0F9AB228C1EF410", "AE6C4F91FE02B1DE", "1C99CE616A229159",
                "F6C9B7ECFF2F6ECD", "C220AFD378F2E80F", "42367BACDBB66DC0", "DA04974888B8C018", "F39404A5A3070C56",
                "13887E2AC1FEFB70", "DBFC5EFB1447B93A", "AB246AEF5D7EF830", "5C96A44BC82EB00C", "178A2A70720ADC88",
                "90FC4555575D3706", "1F28FAF438B06052", "29B226B43F66E5F0", "AC79F224028C6FBE", "81CD83469F8E60E5",
                "F97B052844950578", "653AA775345A0D41", "7495AF5627B17B2A", "7BAEDE2CA9BCA778", "AC49B94AF2F7D8D5",
                "8D30814C7229159B", "72FCB739499A32B8", "1CAF5A42931A42F3", "35E822ACCD0775B2", "30AE680F4EDBCC73",
                "3AB6BCCA4198E19F", "101B8C787CD8DE3D", "FE9C0B22B0DA9168", "D6B2FE5BF1FF178F", "1D17717ED7FB67C9",
                "E173455B6D362F9D", "CF30BF25A91455BF", "E1A9AE779D5895CF", "D4728D158CD9EE96", "225A201374C7E1B8",
                "BC52635AF11CAA04", "0C90748256DAB8DA", "EEA7E043E4412880", "24C39C47F02AAFC2", "47D42B5130CC982B",
                "134ABB1C2C95BF9B", "6EB2396DE7910EEF", "184E1D16BE28BFFB", "C520226B5395B227", "FED1D880638834D6",
                "5F0537B6AE0D89F8", "81E3742EF183BA69", "2033BB7455913DC1", "2CB46A398182424E", "53803FE9AA33513F",
                "420D0DA81D3A8504", "0CE95996CD34A382", "7A93D08FD5048C0B", "57387F22E11AA2FC", "9BC169C3A32C1AFA",
                "6AB950B4E71D434A", "FADDD7A201D9BEBA", "F6D87D6DC316F223", "76E35BC267BF1337", "1C7CFAE2198D1A07",
                "22BD5502D17A0237", "519AED517AFBCAE0", "34AAACCAE82C9A13", "A2757FAD5626AC5F", "83E926B46AC0C2B5",
                "8B6B9F38747AB541", "AA1C5EED41130D9B", "DE8FF32A57157F11", "804F7144E792FD11", "E227F2072C0B3155",
                "5F05958C2A9FDBA2", "B1DA7D580F53E48A", "55910179EFD9E0B0", "811D5F3DD3CBC65D", "AE5CA8292B50BB53",
                "57A2241F414FBCAD", "2888E24602379D83", "F584BF1B9077F85F", "EE181E416EBBC002", "ED1347DC7429CFB4",
                "5D97CF65CE4D9EC0", "890D53425BF94CED", "0BA292D19CE5148A", "84D2D04602A834BD", "A73B33BE5068864F",
                "83B360BE49849BA7", "663576163C51F342", "46D2F349DF191ECD", "A0B46B0C18920C55", "D9A4290F4B9F217A",
                "1C5FC778190ACB4E", "B95B1364B7E7EECD", "ED40DC41F5BFC3AB", "5B157E859FD59169", "C20BA26FD8276496",
                "D34932A94F9CE8BE", "851DC76D0E03802F", "05510909416351D3", "30BD565075997975", "CFCF79ACD1718353",
                "90395E844546B8B0", "95A04192C4A99D52", "AB0F8AEA1FBEED05", "B7AE633E5E5B0B9D", "35223BD9EF30AFA2",
                "8FCD116A4085E1F2", "841F30FF22B171AA", "9C8D7D3C8F2A62AB", "BA05E5F44937CA77", "311CFACDD6F06F9D",
                "C171FE410BE63E31", "03814B11FFB87D3E", "BC68642D76C89F09", "8756CC7ED9D75FF6", "6757414D8C78E34B",
                "6F938EE4BFEFCF39", "2D3A13C3F233037E", "938570777EC3A30D", "9728AE4D851E81A1", "C2555FD6E19C3F38",
                "D51F5C01CBB65D31", "A5C7117E6CBD972E", "00B0242C804B8154", "0EC21FD2D9043834", "5D71C1F8B2792BF8",
                "2F8DC1EDA72C1652", "1338A3790D2424BB", "CD626189FF05FF86", "C51FEDF73205DF8E", "AB27F7448A83A9CE",
                "0D46289E4D15E0FB", "B99FCF3F39E65B81", "E6F0A1169CBD1441", "8997DDCE1478D784", "5B581D25972CEF76",
                "2F7E2C8EA3AE100B", "A5CA820BEC458A34", "BA04897779586515", "CFC2D99BBFA57BC3", "3289C26E0D2A8DCE",
                "3DAF4091DEDD9D52", "D7AE78369D0EF293", "D3A3CA54DEE75273", "BC49B70EC956A03F", "597ED794EAB95D5F",
                "5546CC4FEB26D549", "7D2A20B6CDA86BB5", "CF5D90FF1AF85083", "D60759480D68671D", "449DCFABD01FA9A8",
                "2C300F3C0D32C8B1", "A8C29C56B46E5A97", "5E562AABD22414AC", "EAA77EBE4AFA7198", "4D36EE5BF46B2FC8",
                "2A13AE8CEE6AA8FF", "5C624ABA4135BA8F", "491D6550F48D1126", "A117FA84167472D5", "153364AA485FF4FD",
                "CC901986B08E6F4D", "3225378A5AF745BB", "01A8746A2B7E7182", "10FD8BCC6839F641", "F39404A5A3070C56",
                "CC4281C870E98FAC", "C32DD966C0911ECD", "75D53D58DA0A70C5", "D84144D87358F716", "4420E1E870AC1AC7",
                "EEC04DAFE6659C67", "1EE6ED19E6D1F548", "10088800D9EA8484", "BA0E440265568FC3", "6A79A4027DC9D4C7",
                "7D564FAD598FD71E", "F7775FAE079EB4C9", "E3013B5B058573BB", "2D5FF3FB6874560C", "66909ED4393E998E",
                "3FDD7F237A882F4E", "82463C64AC7D665E", "C79F95A4A56C81C8", "329526DD264F8A07", "3E277CE73B1DD6B6",
                "AA76F8BB4839C72D", "88806A6CF45F5439", "0254BDF538B70B99", "97B37E0DD8EEA2BD", "49E03A838A5C4FFE",
                "F83A31773938C4ED", "0F9314BAED157FE3", "59C738EB7CE00FBC", "9CFC7E5908186F73", "A36065CCDE877BB4",
                "1EAAA733468A6019", "360FC0E131E4CC1C", "25607B762A1912F6", "151FA7D6B6C38BFB", "1DCF229C02EE920C",
                "E44F1A0FAECCA2E4", "BA77D98DE2255D16", "E8E1FFEF014D8191", "6757AB22B326D8D7", "CAFB058DB98410BE",
                "CDF2CB6724C8A377", "6AB950B4E71D434A", "DEBD85FCF06FE7FC", "F8D4DED46C08C557", "F336CE213892CDF0",
                "B8286C2A9BC957A4", "2066C93EDF7A3C10", "B86B77DBFF5E837F", "87CBCC5F55CF43FD", "BC4A994D13CA2CD9",
                "CD626189FF05FF86", "B74A74ADB51394D8", "B9822A1A2109D936", "E5868A2E179903C1", "388903BA3E36418D",
                "95EB34D874063AD6", "8C8C66A7CE733BB0", "7BBF7CC10AFEBDE9", "43F108D358DBF0D4", "4395B49A18044F2A",
                "CF5109A9A6983D7F", "C61E7854F2169888", "BE6EB2FB54D6ECA8", "14728C58CD3E799E", "A375923C1A54C8A5",
                "7AB48632CE35A523", "FCE6BBCE9CCC676E", "8BB67E5E0AFA1592", "285B1FF5FF6784FE", "277A4FAD4B6DB505",
                "76BAE9F2EA376065", "B29823DC293436F9", "D2FA7FA7483B3A92", "D66E7F06AE8FD2B2", "BF9AE5AFDC703102",
                "3F0FFD22EDEE952C", "E628DAF8829B1997", "0E32DA43088F068E", "2D1927F21BBBB9DA", "49F7AA07DAF523BA",
                "C8F8FDCDD0CED748", "BFEDFBF17219D73C", "17FAD1D1923D5FB9", "9FEF66E3274DDB91", "1001FA3B5AE5AD0C",
                "79E86333D9152ED6", "2EB1C753BAB7DA0D", "94CD99C3D1295F28", "F4AD081B7327C65B", "AFF84D2307E0004A",
                "8C4D945B235DF70D", "9430D196ED501BF0", "885D1E52A651F72B", "86762B897D2D7DC8", "BA49CEEB36979C54",
                "3346D32437F20BA7", "D8D72F656297CF6E", "109C0C7EFBBAFF8A", "B16E1D9A13EC8ED0", "0FA523D673D40F8D",
                "44C4A24338491722", "BB9BD15CB1D218AA", "D05C80DCC2FABD6F", "E4E1E9670EEB8EF1", "21262FFB226D913B",
                "736D33A1261A6665", "FD35A67BA0EAFD5B", "AFE2C45CCE183477", "D809EB8109C693FA", "D2F1DDFE9B55FCB0",
                "6C2344567DBED2B5", "4422B3FCE37C6A74", "245FE0EE6155E84B", "F0216CBD4B5FACEA", "7B74C39A819F9565",
                "8DB23551362C3CA0", "E6422F1BA2AF21B9", "EFA99BF359C6EFDC", "A295DD974B576A0E", "8BC3564BEE4C6301",
                "50E38A69412D0CDD", "157D4D5E98CBBB34", "9C926329C9F6A489", "B1D222A23E86CD08", "C411C62E8DF23668",
                "DD19D9775EB46262", "32761ECFE13FCBE6", "084417836778EB4D", "F15829D37A7314E5", "4F7B06B15FEE2707",
                "10DB3275004C79AD", "BEAA74A8913D0445", "E008EA199670C28E", "676C34B32958D680", "76E4A9FE97A497A1",
                "6CB7F4D7E13CC00B", "A12251D86CC4F5DF", "586393DAE93A348A", "A15E06F138A6D461", "AA580F9FD8DD4901",
                "50C5BCD7D0614F0C", "116EA518B037B48A", "A1705FE72C12390B", "953C047DF74D0341", "ABD21234CF9D29E4",
                "855791A5CC995465", "A012A1A8362E3F2D", "9167CAB444658E1C", "3B623E11D26E55E4", "100A976A19BE9230",
                "56637BD09EC70A1E", "DF46663A3EE76DE0", "45408E72328A2F53", "A12012445EB86F26", "CC5CF9D0685A8CAD",
                "5778ECFF8C1C085F", "7094B21B545BBF9E", "6EDADC7C54073FD3", "0CDC5A12BF2EA459", "F05D4B3E557BDAD1",
                "BB2A498F1666A01E", "0D75D870486661B9", "9362E7108C3D98C1", "06087161793B3368", "2224A28409722E98",
                "C3387717CFC1AAD6", "CD86078F76A17B9C", "60538B976EA9965C", "D2E25D5D00C9CC01", "4DB3017CA1BE6B53",
                "B0368AE0514F1247", "4321BE32BB189DF1", "4F83770DE9C5BA09", "F4905FDDB68B6CBF", "8A68A38F955CDA6A",
                "9BC6971147743E8E", "290222CBED992731", "15638B59E525F5A0", "419FD9CAE4EF021F", "F95A4B6A78DBA7ED",
                "6146A0CC3DBDB82A", "C6113F6D40D21E50", "90CA7BD1A145331E", "A1E2270416BD555F", "B43D6A9230EAEA2F",
                "EC57F08BF05A0EEC", "1F59C2EA1721D03D", "7F56DB73A960CD06", "79CBDFDADA190B10", "7DD10E9EFB3C0351",
                "C1CCB89780B9C8C9", "A97D417450C5AE3C", "B5767CE314B55F4C", "576E5F13051AD639", "F277D3FA64CBC89B"
            };
            //@NoUseNewKeyEx return 1;//如果没有使用这个功能，直接返回1
            //@NoSupNewKeyEx return 2;//如果该锁不支持这个功能，直接返回2
            for (n = 0; n < 255; n++)
            {
                ret = FindPort(n, ref DevicePath);
                if (ret != 0) return ret;
                ret = EncString_New(EncInString[myrnd], ref outstring, DevicePath);
                if ((ret == 0) && (outstring.CompareTo(EncOutString[myrnd]) == 0)) return 0;
            }

            return -92;
        }
    }
}