using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Imaging; using System.IO; using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; namespace Helper { public class CV300EHelper { #region 指纹特征提取函数接口 /// /// 版本信息获取 /// 函数原型：int __stdcall FP_GetVersion(unsigned char code[4]) /// /// unsigned char code[4] 版本信息格式为XXYY，XX为开发者代码，YY为版本号。如“1201” 则code的填写方式为：，code[0]=‘1’ code[1]=，‘2’ code[3]=，‘0’ code[4]=,‘1’。输出参数。 /// <returns>调用成功，返回1；否则返回错误代码，错误代码值应符合B.4的要求。输出参数。</returns> [DllImport("ID_Fpr.dll", EntryPoint = "FP_GetVersion", CharSet = CharSet.Auto, SetLastError = false)] public static extern int FP_GetVersion(System.IntPtr code); /// /// 初始化操作 /// 函数原型：int __stdcall FP_Begin() /// /// <returns>调用成功返回 1。否则返回错误代码，调用 LIVESCAN_GetErrInfo 函数获取错误信息。错误代码值符合 B.4 的要求。</returns> [DllImport("ID_Fpr.dll", EntryPoint = "FP_Begin", CharSet = CharSet.Auto, SetLastError = false)] public static extern int FP_Begin(); /// /// 指纹图像特征提取 /// 函数原型：int __stdcall FP_FeatureExtract(unsigned char cScannerType,unsigned char cFingerCode,unsigned char * pFingerImgBuf,unsigned char * pFeatureData) /// /// unsigned char cScannerType 指纹采集器代码。输入参数。 /// unsigned char cFingerCode 指位代码。输入参数。 /// unsigned char * pFingerImgBuf 指纹图像数据指针，指纹图像为RAW格式。输入参数。 /// unsigned char * pFeatureData 指纹特征数据指针，存储生成的指纹特征数据，由调用者分配内存空间，输出参数。 /// <returns>调用成功，返回1；否则返回错误代码，错误代码值应符合B.4的要求</returns> [DllImport("ID_Fpr.dll", EntryPoint = "FP_FeatureExtract", CharSet = CharSet.Auto, SetLastError = false)] public static extern int FP_FeatureExtract(byte cScannerType, byte cFingerCode, System.IntPtr pFingerImgBuf, System.IntPtr pFeatureData); /// /// 指纹图像数据与指纹特征数据比对 /// 函数原型：int __stdcall FP_FeatureMatch(unsigned char * pFeatureData1,unsigned char* pFeatureData2,float * pfSimilarity) /// 对两个指纹特征数据进行比对，得到相似度值 /// /// unsigned char * pFeatureData1 指纹特征数据指针1。输入参数。 /// unsigned char * pFeatureData2 指纹特征数据指针2。输入参数。 /// float * pfSimilarity 相似度，取值范围为0.00 ～ 1.00，值0.00表示不匹配，值1.00 表示完全匹配。输出参数。 /// <returns>调用成功，返回1；否则返回错误代码，错误代码值应符合B.4的要求</returns> [DllImport("ID_Fpr.dll", EntryPoint = "FP_FeatureMatch", CharSet = CharSet.Auto, SetLastError = false)] public static extern int FP_FeatureMatch(System.IntPtr pFeatureData1, System.IntPtr pFeatureData2, ref float pfSimilarity); /// /// 指纹图像数据与指纹特征数据比对 /// 函数原型：int __stdcall FP_ImageMatch(unsigned char * pFingerImgBuf,unsigned char *pFeatureData,float * pfSimilarity)。 /// 对指纹图像数据与指纹特征数据进行比对，得到相似度值。 /// /// unsigned char * pFingerImgBuf 指纹图像数据指针,指纹图像为RAW格式。输入参数。 /// unsigned char * pFeatureData 指纹特征数据指针。输入参数。 /// float * pfSimilarity 相似度，取值范围为0.00 ～ 1.00，值0.00表示不匹配，值1.00 表示完全匹配。输出参数。 /// <returns>调用成功，返回1；否则返回错误代码，错误代码值应符合B.4的要求</returns> [DllImport("ID_Fpr.dll", EntryPoint = "FP_ImageMatch", CharSet = CharSet.Auto, SetLastError = false)] public static extern int FP_ImageMatch(System.IntPtr pFingerImgBuf, System.IntPtr pFeatureData, ref float pfSimilarity); /// /// 指纹图像数据压缩 /// 函数原型：int __stdcall FP_Compress(unsigned char cScannerType, unsigned char cEnrolResult,unsigned char cFingerCode, unsigned char* pFingerImgBuf,int nCompressRatio, unsigned char* pCompressedImgBuf, unsigned char strBuf[256])。 /// 对指纹图像数据进行压缩。 /// /// unsigned char cScannerType 指纹采集器代码。输入参数。 /// unsigned char cEnrolResult 注册结果代码。输入参数。 /// unsigned char cFingerCode 指位代码。输入参数。 /// unsigned char * pFingerImgBuf 指纹图像数据指针，指纹图像为RAW格式。输入参数。 /// int nCompressRatio 指纹图像数据压缩倍数。输入参数。 /// unsigned char * pCompressedImgBuf 指纹压缩图像数据指针，调用者在调用此函数前，应当分配不小于20 480字节的内存，指纹压缩图像数据文件结构应符合附录A要求。输出参数。 /// unsigned char strBuf[256] 错误信息，如果压缩图像发生错误，并且返回值为-9的情况下，strBuf填写错误信息。错误信息为以数值0结尾的字符串，采用GB 13000中规定的字符。输出参数。 /// <returns>调用成功，返回1；否则返回错误代码，错误代码值应符合B.4的要求。</returns> [DllImport("ID_Fpr.dll", EntryPoint = "FP_Compress", CharSet = CharSet.Auto, SetLastError = false)] public static extern int FP_Compress(byte cScannerType, byte cEnrolResult, byte cFingerCode, System.IntPtr pFingerImgBuf, int nCompressRatio, System.IntPtr pCompressedImgBuf, byte[] strBuf); /// /// 指纹图像数据复现 /// 函数原型：int __stdcall FP_Decompress(unsigned char * pCompressedImgBuf,unsigned char* pFingerImgBuf,unsigned char strBuf[256])。 /// 对指纹原始图像数据进行复现。 /// /// unsigned char * pCompressedImgBuf 指纹压缩图像数据指针，压缩图像数据长度不大 于20 480字节。输入参数。 /// unsigned char * pFingerImgBuf 指纹复现图像数据指针，指纹图像为RAW格式，调用者在调用此函数前，应当分配92 160字节的内存。输出参数。 /// unsigned char strBuf[256] 错误信息，如果压缩图像发生错误，并且返回值为-9的情况下，strBuf填写错误信息。错误信息为以数值0结尾的字符串，采用GB 13000中规定的 字符。输出参数。 /// <returns>调用成功，返回1；否则返回错误代码，错误代码值应符合B.4的要求</returns> [DllImport("ID_Fpr.dll", EntryPoint = "FP_Decompress", CharSet = CharSet.Auto, SetLastError = false)] public static extern int FP_Decompress(System.IntPtr pCompressedImgBuf, System.IntPtr pFingerImgBuf, byte[] strBuf); /// /// 指纹图像质量值获取 /// 函数原型：int __stdcall FP_GetQualityScore(unsigned char * pFingerImgBuf,unsigned char* pnScore)。 /// 获取指纹图像的质量值 /// /// unsigned char * pFingerImgBuf 指纹图像数据指针，指纹图像为RAW格式。输入参数。 /// unsigned char * pnScore 指纹图像质量值指针，指纹图像质量值取值范围为00H ～ 64H，值01H表示最低质量，值64H表示最高质量，值00H表示未知。 /// <returns>调用成功，返回1；否则返回错误代码，错误代码值应符合B.4的要求。</returns> [DllImport("ID_Fpr.dll", EntryPoint = "FP_GetQualityScore", CharSet = CharSet.Auto, SetLastError = false)] public static extern int FP_GetQualityScore(System.IntPtr pFingerImgBuf, ref int pnScore); /// /// 生成“注册失败”指纹特征数据 /// 函数原型：int __stdcall FP_GenFeatureFromEmpty1(unsigned char cScannerType,unsigned char cFingerCode,unsigned char * pFeatureData) /// 本函数针对“注册失败”手指的情况，生成“注册失败”指纹特征数据。其中，字段5设置为02H；字段9、字段10均设置为00H。 /// /// unsigned char cScannerType 指纹采集器代码。输入参数。 /// unsigned char cFingerCode 指位代码。输入参数。 /// unsigned char * pFeatureData 指纹特征数据指针，存储生成的指纹特征数据，由调用者分配内存空间，输出参数。 /// <returns>调用成功，返回1；否则返回错误代码，错误代码值应符合B.4的要求</returns> [DllImport("ID_Fpr.dll", EntryPoint = "FP_GenFeatureFromEmpty1", CharSet = CharSet.Auto, SetLastError = false)] public static extern int FP_GenFeatureFromEmpty1(byte cScannerType, byte cFingerCode, System.IntPtr pFeatureData); /// /// 生成“未注册”指纹特征数据 /// 函数原型：int __stdcall FP_GenFeatureFromEmpty2(unsigned char cFingerCode,unsigned char * pFeatureData) /// 本函数针对“未注册”手指的情况，生成“未注册”指纹特征数据。其中，字段5设置为03H；字段6设置为61H、62H或63H；字段7、字段9、字段10均设置为00H。 /// /// unsigned char cFingerCode 指位代码。输入参数。 /// unsigned char * pFeatureData 指纹特征数据指针，存储生成的指纹特征数据，由调用者分配内存空间，输出参数。 /// <returns>调用成功，返回1；否则返回错误代码，错误代码值应符合B.4的要求。</returns> [DllImport("ID_Fpr.dll", EntryPoint = "FP_GenFeatureFromEmpty2", CharSet = CharSet.Auto, SetLastError = false)] public static extern int FP_Decompress(byte cFingerCode, System.IntPtr pFeatureData); /// /// 结束操作 /// 函数原型：int __stdcall FP_End() /// /// <returns>调用成功，返回1；否则返回错误代码，错误代码值应符合B.4的要求。</returns> [DllImport("ID_Fpr.dll", EntryPoint = "FP_End", CharSet = CharSet.Auto, SetLastError = false)] public static extern int FP_End(); #endregion #region 指纹仪函数接口 /// /// 初始化采集器 /// 函数原型：int _stdcall LIVESCAN_Init()。 /// 初始化采集器，分配相应的资源。 /// 在所有接口函数中，通常首先调用此函数。只需要调用一次，允许重复调用，其结果与一次调用相同。 /// /// <returns>调用成功返回1。否则返回错误代码，调用LIVESCAN_GetErrInfo函数获取错误信息。错误代码值符合A.4的要求。</returns> [DllImport("ID_FprCap.dll", EntryPoint = "LIVESCAN_Init", CharSet = CharSet.Auto, SetLastError = false)] public static extern int LIVESCAN_Init(); /// /// 释放采集器 /// 函数原型：int _stdcall LIVESCAN_Close()。 /// 关闭指纹采集器，释放分配的资源。 /// 调用此函数后，在没有调用 LIVESCAN_Init 函数之前，仅可调用 LIVESCAN_GetVersion、LIVESCAN_GetDesc 和 LIVESCAN_GetErrorInfo 函数。 /// 调用此函数后，应重新调用 LIVESCAN_Init 来初始化采集器。 /// /// <returns>调用成功返回 1。否则返回错误代码，调用 LIVESCAN_GetErrInfo 函数获取错误信息。错误代码值符合 A.4 的要求。</returns> [DllImport("ID_FprCap.dll", EntryPoint = "LIVESCAN_Close", CharSet = CharSet.Auto, SetLastError = false)] public static extern int LIVESCAN_Close(); /// /// 获得采集器通道数量 /// 函数原型：int _stdcall LIVESCAN_GetChannelCount()。 /// 获得采集器可以使用的通道数量及通道号。 /// /// <returns>调用成功返回通道数量（＞0）。否则返回错误代码，调用 LIVESCAN_GetErrInfo 函数获取错误信息。错误代码值符合 A.4 的要求。</returns> [DllImport("ID_FprCap.dll", EntryPoint = "LIVESCAN_GetChannelCount", CharSet = CharSet.Auto, SetLastError = false)] public static extern int LIVESCAN_GetChannelCount(); /// /// 获得采集器采集图像的宽度、高度的最大值 /// 函数原型：int _stdcall LIVESCAN_GetMaxImageSize（int nChannel,int * pnWidth, int * pnHeight)。 /// 获得采集器可采集图像的宽度、高度的最大值。 /// /// int nChannel 通道号。输入参数。 /// int * pnWidth 存放图像宽度的整形指针。输出参数。 /// int * pnHeight 存放图像高度的整形指针。输出参数。 /// <returns>调用成功返回 1。否则返回错误代码，调用 LIVESCAN_GetErrInfo 函数获取错误信息。错误代码值符合 A.4 的要求。</returns> [DllImport("ID_FprCap.dll", EntryPoint = "LIVESCAN_GetMaxImageSize", CharSet = CharSet.Auto, SetLastError = false)] public static extern int LIVESCAN_GetMaxImageSize(int nChannel, ref int pnWidth, ref int pnHeight); /// /// 获得采集器当前的亮度 /// 函数原型：int _stdcall LIVESCAN_GetBright(int nChannel,int * pnBright)。 /// 获得采集器当前亮度。 /// /// int nChannel 通道号。输入参数。 /// int * pnBright 存放当前亮度的整形指针。输出参数。 /// <returns>调用成功返回 1。否则返回错误代码 ,调用 LIVESCAN_GetErrInfo 函数获取错误信息。错误代码值符合 A.4 的要求。</returns> [DllImport("ID_FprCap.dll", EntryPoint = "LIVESCAN_GetBright", CharSet = CharSet.Auto, SetLastError = false)] public static extern int LIVESCAN_GetBright(int nChannel, ref int pnBright); /// /// 设置采集器当前的亮度 /// 函数原型：int _stdcall LIVESCAN_SetBright(int nChannel, int nBright)。 /// 设置采集器当前亮度 /// /// int nChannel 通道号。输入参数。 /// int nBright 亮度，范围为 0～255，输入参数。 /// <returns>调用成功返回 1。否则返回错误代码，调用 LIVESCAN_GetErrInfo 函数获取错误信息。错误代码值符合 A.4 的要求。</returns> [DllImport("ID_FprCap.dll", EntryPoint = "LIVESCAN_SetBright", CharSet = CharSet.Auto, SetLastError = false)] public static extern int LIVESCAN_SetBright(int nChannel, int nBright); /// /// 获得采集器当前对比度 /// 函数原型：int _stdcall LIVESCAN_GetContrast(int nChannel,int * pnContrast)。 /// 获得采集器当前对比度。 /// /// int nChannel 通道号。输入参数。 /// int * pnContrast 存放当前对比度的整型指针。输出参数。 /// <returns>调用成功返回 1。否则返回错误代码，调用 LIVESCAN_GetErrInfo 函数获取错误信息。错误代码值符合 A.4 的要求。</returns> [DllImport("ID_FprCap.dll", EntryPoint = "LIVESCAN_GetContrast", CharSet = CharSet.Auto, SetLastError = false)] public static extern int LIVESCAN_GetContrast(int nChannel, ref int pnContrast); /// /// 设置采集器当前对比度 /// 函数原型：int _stdcall LIVESCAN_SetContrast(int nChannel,int Contrast)。 /// 设置采集器当前对比度。 /// /// int nChannel 通道号。输入参数。 /// int nContrast 对比度, 范围0～255。输入参数。 /// <returns>调用成功返回1。否则返回错误代码，调用LIVESCAN_GetErrInfo函数获取错误信息。错误代码值符合A.4 的要求。</returns> [DllImport("ID_FprCap.dll", EntryPoint = "LIVESCAN_SetContrast", CharSet = CharSet.Auto, SetLastError = false)] public static extern int LIVESCAN_SetContrast(int nChannel, int nContrast); /// /// 获得当前图像的采集位置、宽度和高度 /// 函数原型：int _stdcall LIVESCAN_GetCaptWindow(int nChannel,int * pnOriginX, int * pnOriginY,int * pnWidth, int * pnHeight)。 /// 获得采集器当前图像的采集位置、宽度和高度。当前图像宽度初始值为 256，高度初始值为360。 /// /// int nChannel 通道号。输入参数。 /// int *pnOriginX 存放图像采集窗口的采集原点坐标X值的整型指针。输出参数。 /// int *pnOriginY 存放图像采集窗口的采集原点坐标Y值的整型指针。输出参数。 /// int *pnWidth 存放采集图像宽度的整形指针。输出参数。 /// int *pnHeight 存放采集图像高度的整形指针。输出参数。 /// <returns>调用成功返回 1。否则返回错误代码，调用 LIVESCAN_GetErrInfo 函数获取错误信息。错误代码值符合 A.4 的要求。</returns> [DllImport("ID_FprCap.dll", EntryPoint = "LIVESCAN_GetCaptWindow", CharSet = CharSet.Auto, SetLastError = false)] public static extern int LIVESCAN_GetCaptWindow(int nChannel, ref int pnOriginX, ref int pnOriginY, ref int pnWidth, ref int pnHeight); /// /// 设置当前图像的采集位置、宽度和高度 /// 函数原型：int _stdcall LIVESCAN_SetCaptWindow(int nChannel,int nOriginX, int nOriginY,int nWidth,int nHeight)。 /// 设置采集器当前图像的采集位置、宽度和高度。 /// /// int nChannel 通道号。输入参数。 /// int nOriginX 图像采集窗口的采集原点坐标 X 值。输入参数。 /// int nOriginY 图像采集窗口的采集原点坐标 Y 值。输入参数。 /// int nWidth 采集图像的宽度。对于居民身份证用单指指纹采集，应大于等于 256。否则应返回参数错误代码。输入参数。 /// int nHeight 采集图像的高度。对于居民身份证用单指指纹采集，应大于等于 360。否则应返回参数错误代码。输入参数。 /// <returns>调用成功返回 1。否则返回错误代码，调用 LIVESCAN_GetErrInfo 函数获取错误信息。错误代码值符合 A.4的要求。</returns> [DllImport("ID_FprCap.dll", EntryPoint = "LIVESCAN_SetCaptWindow", CharSet = CharSet.Auto, SetLastError = false)] public static extern int LIVESCAN_SetCaptWindow(int nChannel, int nOriginX, int nOriginY, int nWidth, int nHeight); /// /// 准备采集一帧图像 /// 函数原型：int _stdcall LIVESCAN_BeginCapture(int nChannel)。 /// 采集图像的一个前缀函数，使得采集器有机会进行另外一个采集之前的初始化工作。 /// /// int nChannel 通道号。输入参数。 /// <returns>调用成功返回 1。否则返回错误代码，调用 LIVESCAN_GetErrInfo 函数获取错误信息。错误代码值符合 A.4 的要求。</returns> [DllImport("ID_FprCap.dll", EntryPoint = "LIVESCAN_BeginCapture", CharSet = CharSet.Auto, SetLastError = false)] public static extern int LIVESCAN_BeginCapture(int nChannel); /// /// 结束采集一帧图像 /// 函数原型：int _stdcall LIVESCAN_EndCapture(int nChannel)。 /// 结束采集一帧图像或预览图像。 /// /// int nChannel 通道号。输入参数。 /// <returns>调用成功返回1。否则返回错误代码，调用LIVESCAN_GetErrInfo函数获取错误信息。错误代码值符合A.4 的要求。</returns> [DllImport("ID_FprCap.dll", EntryPoint = "LIVESCAN_EndCapture", CharSet = CharSet.Auto, SetLastError = false)] public static extern int LIVESCAN_EndCapture(int nChannel); /// /// 采集一帧图像 /// 函数原型：int _stdcall LIVESCAN_GetFPRawData(int nChannel,unsigned char *pRawData)。 /// /// int nChannel通道号。输入参数。 /// unsigned char* pRawData指向存放采集数据的内存块，调用者分配。 返回图像数据，大小应为：当前图像采集宽度×当前图像采集高度。输出参数。 /// <returns>调用成功返回1。否则返回错误代码，调用LIVESCAN_GetErrInfo函数获取错误信息。错误代码值符合 A.4 的要求。</returns> [DllImport("ID_FprCap.dll", EntryPoint = "LIVESCAN_GetFPRawData", CharSet = CharSet.Auto, SetLastError = false)] public static extern int LIVESCAN_GetFPRawData(int nChannel, System.IntPtr pRawData); /// /// 采集一帧BMP格式图像数据 /// 函数原型：int _stdcall LIVESCAN_GetFPBmpData(int nChannel, unsigned char * pBmpData)。 /// 采集一帧8位灰度 BMP 格式图像。 /// /// int nChannel通道号。输入参数。 /// unsigned char* pBmpData 指向存放8位灰度BMP格式采集数据的内存块，调用者分配。返回8位灰度BMP格式图像数据。大小应为：当前图像采集宽度×当前图像采集高度+1078。输出参数。 /// <returns>调用成功，返回 1。否则返回错误代码，调用 LIVESCAN_GetErrInfo 函数获取错误信息。错误代码值符合 A.4 的要求。</returns> [DllImport("ID_FprCap.dll", EntryPoint = "LIVESCAN_GetFPBmpData", CharSet = CharSet.Auto, SetLastError = false)] public static extern int LIVESCAN_GetFPBmpData(int nChannel, System.IntPtr pBmpData); /// /// 调用采集器的属性设置对话框 /// 函数原型：int _stdcall LIVESCAN_Setup()。 /// 此函数弹出一个模式对话框，用户可以设置除去对比度、亮度、采集窗口参数外的其它参数，如GAMMA值等，使得设置适合采集器本身的特点。 /// /// <returns>调用成功返回 1。否则返回错误代码，调用 LIVESCAN_GetErrInfo 函数获取错误信息。错误代码值符合 A.4 的要求。</returns> [DllImport("ID_FprCap.dll", EntryPoint = "LIVESCAN_Setup", CharSet = CharSet.Auto, SetLastError = false)] public static extern int LIVESCAN_Setup(); /// /// 采集器是否支持设置对话框 /// 函数原型：int _stdcall LIVESCAN_IsSupportSetup()。 /// 此函数用来确认是否支持设置对话框。 /// /// <returns>若采集接口支持LIVESCAN_setup，则返回1，否则返回0。否则返回错误代码，调用 LIVESCAN_GetErrInfo 函数获取错误信息。错误代码值符合A.4的要求。</returns> [DllImport("ID_FprCap.dll", EntryPoint = "LIVESCAN_IsSupportSetup", CharSet = CharSet.Auto, SetLastError = false)] public static extern int LIVESCAN_IsSupportSetup(); /// /// 取得接口规范的版本 /// 函数原型：int ¬_stdcall LIVESCAN_GetVersion()。 /// 获得接口版本号。 /// /// <returns>获得接口规范的版本。当前版本为1.00，返回值为100。若以后扩展接口，则需要修改此版本号。否则返回错误代码，调用LIVESCAN_GetErrorInfo函数获取错误信息。错误代码值应符合 A.4的要求。</returns> [DllImport("ID_FprCap.dll", EntryPoint = "LIVESCAN_GetVersion", CharSet = CharSet.Auto, SetLastError = false)] public static extern int LIVESCAN_GetVersion(); /// /// 获得接口规范的说明 /// 函数原型：int _stdcall LIVESCAN_GetDesc(char pszDesc[1024])。 /// 获得接口说明，不需要初始化就可以调用。pszDesc以数值0结尾的字符串，采用GB13000 中规定的字符。 /// /// char pszDesc[1024]存放接口说明，其中pszDesc[0]用于存储采集器代码，缺省为FFH。 输出参数。 /// <returns>调用成功返回1。否则返回错误代码，调用LIVESCAN_GetErrorInfo函数获取错误信息。错误代码值应符合 A.4的要求</returns> [DllImport("ID_FprCap.dll", EntryPoint = "LIVESCAN_GetDesc", CharSet = CharSet.Auto, SetLastError = false)] public static extern int LIVESCAN_GetDesc(System.IntPtr pszDesc); /// /// 设置存放采集数据的内存块为空 /// 函数原型：int _stdcall LIVESCAN_SetBufferEmpty(unsigned char * pImageData, long imageLength）。 /// 将存放采集数据的内存块中的每一个字节的值置为0x00。 /// /// unsigned char * pImageData 指向存放采集数据的内存块。输入参数。 /// long imageLength 存放采集数据的内存块长度。输入参数。 /// <returns>调用成功返回1。否则返回错误代码，调用 LIVESCAN_GetErrInfo 函数获取错误信息。错误代码值符合A.4的要求。</returns> [DllImport("ID_FprCap.dll", EntryPoint = "LIVESCAN_SetBufferEmpty", CharSet = CharSet.Auto, SetLastError = false)] public static extern int LIVESCAN_SetBufferEmpty(System.IntPtr pImageData, long imageLength); /// /// 获得采集接口错误信息 /// 函数原型：int _stdcall LIVESCAN_GetErrorInfo(int nErrorNo,char pszErrorInfo[256])。 /// pszErrorInfo 采用GB13000中规定的字符。 /// /// char pszErrorInfo[256]用来存放错误信息的内存块，错误信息的长度不能超过 256 个字节。输出参数。 /// int nErrorNo 错误代码(＜0)。输入参数。 /// <returns>若为合法的错误代码返回 1，pszErrorInfo中为错误信息。若 nErrorNo 为非法的错误代码，则返回-6，同时设置 pszErrorInfo为“非法错误号”错误。</returns> [DllImport("ID_FprCap.dll", EntryPoint = "LIVESCAN_GetErrorInfo", CharSet = CharSet.Auto, SetLastError = false)] public static extern int LIVESCAN_GetErrorInfo(int nErrorNo, System.IntPtr pszErrorInfo); [DllImport("Kernel32.dll")] static extern bool QueryPerformanceCounter(ref long count); [DllImport("Kernel32.dll")] static extern bool QueryPerformanceFrequency(ref long count); #endregion #region 二代证接口 /// /// 初始化连接 /// 原 型：int CVR_InitComm (int Port) /// 本函数用于PC与华视电子第二代居民身份证阅读器的连接。 /// /// 连接串口（COM1~COM16）或USB口(1001~1016)[1,串口1],[2,串口2],[3,串口3],[4,串口4],[1001,USB口1],[1002,USB口2],[1003,USB口3],[1004,USB口4] /// <returns>[1,正确],[2,端口打开失败],[0,动态库加载失败]</returns> [DllImport("termb.dll", EntryPoint = "CVR_InitComm", CharSet = CharSet.Auto, SetLastError = false)] public static extern int CVR_InitComm(int Port);//声明外部的标准动态库, 跟Win32API是一样的 /// /// 卡认证 /// 原 型：int CVR_Authenticate (void) /// 本函数用于读卡器和卡片之间的合法身份确认。卡认证循环间隔大于300ms。 /// /// <returns>[值,意义,说明][1,正确,卡片认证成功],[2,错误,寻卡失败],[3,错误,选卡失败],[0,错误,初始化失败]</returns> [DllImport("termb.dll", EntryPoint = "CVR_Authenticate", CharSet = CharSet.Auto, SetLastError = false)] public static extern int CVR_Authenticate(); /// /// 读卡操作 /// 原 型：int CVR_Read_Content(int active) /// 本函数用于通过阅读器从第二代居民身份证中读取相应信息。卡认证成功以后才可做读卡操作，读卡完毕若继续读卡应移走二代证卡片重新放置做卡认证。 /// 读卡成功后在termb.dll文件所在路径下生成wz.txt（文字信息）和zp.bmp（照片信息） /// wz.txt内容示例如下： /// 张红叶 /// 女 /// 汉 /// 1988-11-18 /// 河北省邯郸市临漳县称勾镇称勾东村复兴路25号 /// 130423198811184328 /// 临漳县公安局 /// 2011.03.30-2021.03.30 /// /// active：兼容以前版本，无实际意义 /// <returns>[1,正确],[2,错误],[99,异常]</returns> [DllImport("termb.dll", EntryPoint = "CVR_Read_Content", CharSet = CharSet.Auto, SetLastError = false)] public static extern int CVR_Read_Content(int Active); /// /// 读取文字,照片，指纹，操 /// 原 型：int CVR_Read_FPContent () /// 本函数用于通过阅读器从第二代居民身份证中读取相应信息。卡认证成功以后才可做读卡操作，读卡完毕若继续读卡应移走二代证卡片重新放置做卡认证。 /// 读卡成功后在termb.dll文件所在路径下生成wz.txt（文字信息）和zp.bmp（照片信息） /// wz.txt内容示例如下： /// 张红叶 /// 女 /// 汉 /// 1988-11-18 /// 河北省邯郸市临漳县称勾镇称勾东村复兴路25号 /// 130423198811184328 /// 临漳县公安局 /// 2011.03.30-2021.03.30 /// /// <returns>[1,正确],[0,错误]</returns> [DllImport("termb.dll", EntryPoint = "CVR_Read_FPContent", CharSet = CharSet.Auto, SetLastError = false)] public static extern int CVR_Read_FPContent(); /// /// 关闭连接 /// 原 型：int CVR_CloseComm(void) /// /// <returns>[1,正确],[0,错误]</returns> [DllImport("termb.dll", EntryPoint = "CVR_CloseComm", CharSet = CharSet.Auto, SetLastError = false)] public static extern int CVR_CloseComm(); /// /// 得到姓名信息 /// 原 型：int GetPeopleName(char *strTmp, int *strLen) /// /// *strTmp 返回的信息缓存指针。 /// *strLen 返回的信息长度指针。 /// <returns>[1,正确],[0,错误]</returns> [DllImport("termb.dll", EntryPoint = "GetPeopleName", CharSet = CharSet.Ansi, SetLastError = false)] public static extern int GetPeopleName(ref byte strTmp, ref int strLen); /// /// 得到民族信息 /// /// *strTmp 返回的信息缓存指针。 /// *strLen 返回的信息长度指针。 /// <returns>[1,正确],[0,错误]</returns> [DllImport("termb.dll", EntryPoint = "GetPeopleNation", CharSet = CharSet.Ansi, SetLastError = false)] public static extern int GetPeopleNation(ref byte strTmp, ref int strLen); /// /// 得到出生日期 /// /// *strTmp 返回的信息缓存指针。 /// *strLen 返回的信息长度指针。 /// <returns>[1,正确],[0,错误]</returns> [DllImport("termb.dll", EntryPoint = "GetPeopleBirthday", CharSet = CharSet.Ansi, SetLastError = false, CallingConvention = CallingConvention.StdCall)] public static extern int GetPeopleBirthday(ref byte strTmp, ref int strLen); /// /// 得到地址信息 /// /// *strTmp 返回的信息缓存指针。 /// *strLen 返回的信息长度指针。 /// <returns>[1,正确],[0,错误]</returns> [DllImport("termb.dll", EntryPoint = "GetPeopleAddress", CharSet = CharSet.Ansi, SetLastError = false, CallingConvention = CallingConvention.StdCall)] public static extern int GetPeopleAddress(ref byte strTmp, ref int strLen); /// /// 得到身份证号信息 /// /// *strTmp 返回的信息缓存指针。 /// *strLen 返回的信息长度指针。 /// <returns>[1,正确],[0,错误]</returns> [DllImport("termb.dll", EntryPoint = "GetPeopleIDCode", CharSet = CharSet.Ansi, SetLastError = false, CallingConvention = CallingConvention.StdCall)] public static extern int GetPeopleIDCode(ref byte strTmp, ref int strLen); /// /// 得到发证机关信息 /// /// *strTmp 返回的信息缓存指针。 /// *strLen 返回的信息长度指针。 /// <returns>[1,正确],[0,错误]</returns> [DllImport("termb.dll", EntryPoint = "GetDepartment", CharSet = CharSet.Ansi, SetLastError = false, CallingConvention = CallingConvention.StdCall)] public static extern int GetDepartment(ref byte strTmp, ref int strLen); /// /// 得到有效开始日期 /// /// *strTmp 返回的信息缓存指针。 /// *strLen 返回的信息长度指针。 /// <returns>[1,正确],[0,错误]</returns> [DllImport("termb.dll", EntryPoint = "GetStartDate", CharSet = CharSet.Ansi, SetLastError = false, CallingConvention = CallingConvention.StdCall)] public static extern int GetStartDate(ref byte strTmp, ref int strLen); /// /// 得到有效截止日期 /// /// *strTmp 返回的信息缓存指针。 /// *strLen 返回的信息长度指针。 /// <returns>[1,正确],[0,错误]</returns> [DllImport("termb.dll", EntryPoint = "GetEndDate", CharSet = CharSet.Ansi, SetLastError = false, CallingConvention = CallingConvention.StdCall)] public static extern int GetEndDate(ref byte strTmp, ref int strLen); /// /// 得到性别信息 /// /// *strTmp 返回的信息缓存指针。 /// *strLen 返回的信息长度指针。 /// <returns>[1,正确],[0,错误]</returns> [DllImport("termb.dll", EntryPoint = "GetPeopleSex", CharSet = CharSet.Ansi, SetLastError = false, CallingConvention = CallingConvention.StdCall)] public static extern int GetPeopleSex(ref byte strTmp, ref int strLen); /// /// 读取指纹信息 /// 函数原型：int GetFPDate(unsigned char* pucFPMsgValue,int* nlen) /// 本函数用于通过阅读器从第二代居民身份证中读取指纹信息。CVR_Read_FPContent()调用成功以后才可以调用该函数 /// 以下是指纹信息的相关说明，供调用者参考： /// 第一枚指纹信息： /// pucFPMsgValue[0] 字段文件头类型，记录字符“C”（43H） /// pucFPMsgValue[1] 指纹算法版本号 /// pucFPMsgValue[2] 指纹采集器代码 /// pucFPMsgValue[3] 指纹算法开发者代码 /// pucFPMsgValue[4] 注册结果代码，01H 表示“注册成功”，02H 表示“注册失败”，03H 表示“未注册”，09H 表示“未知” /// pucFPMsgValue[5] 指位代码 具体见指位说明 /// pucFPMsgValue[6] 指纹质量值，以00H～64H来表示，值01H表示最低质量，值64H表示最高质量，值00H表示“未知” /// 第二枚指纹信息： /// pucFPMsgValue[512] 字段文件头类型，记录字符“C”（43H） /// pucFPMsgValue[513] 指纹算法版本号 /// pucFPMsgValue[514] 指纹采集器代码 /// pucFPMsgValue[515] 指纹算法开发者代码 /// pucFPMsgValue[516] 注册结果代码，01H 表示“注册成功”，02H 表示“注册失败”，03H 表示“未注册”，09H 表示“未知” /// pucFPMsgValue[517] 指位代码 具体见指位说明 /// pucFPMsgValue[518] 指纹质量值，以00H～64H来表示，值01H表示最低质量，值64H表示最高质量，值00H表示“未知” /// 指位码说明：[pucFPMsgValue[5or517],指位] /// [0BH,右手拇指],[0CH,右手食指],[0DH,右手中指],[0EH,右手环指],[0FH,右手小指] /// [10H,左手拇指],[11H,左手食指],[12H,左手中指],[13H,左手环指],[14H,左手小指] /// [61H,右手不确定指位],[62H,左手不确定指位],[63H,其他不确定指位] /// /// pucFPMsgValue 存放指纹信息的内存缓冲，大小由调用者分配1024字节大小。 /// nlen 指纹数据的大小，传出参数，0 表示没有指纹信息，大于0表示 存在指纹信息。一个指纹信息转占512字节大小，身份证中一般存储两个指纹信息。 /// <returns>[1,正确],[0,错误]</returns> [DllImport("termb.dll", EntryPoint = "GetFPDate", CharSet = CharSet.Ansi, SetLastError = false, CallingConvention = CallingConvention.StdCall)] public static extern int GetFPDate(ref byte strTmp, ref int strLen); /// /// 得到安全模块号 /// /// *strTmp 返回的信息缓存指针。 /// <returns>[1,正确],[0,错误]</returns> [DllImport("termb.dll", EntryPoint = "CVR_GetSAMID", CharSet = CharSet.Ansi, SetLastError = false, CallingConvention = CallingConvention.StdCall)] public static extern int CVR_GetSAMID(ref byte strTmp); /// /// /// /// *strTmp 返回的信息缓存指针。 /// <returns>[1,正确],[0,错误]</returns> [DllImport("termb.dll", EntryPoint = "GetManuID", CharSet = CharSet.Ansi, SetLastError = false, CallingConvention = CallingConvention.StdCall)] public static extern int GetManuID(ref byte strTmp); #endregion #region 语音提示接口 /// /// 原 型：int SendReport (int nIndex) /// 本函数用于PC与华视电子第二代居民身份证阅读器的连接。 /// 参数:nIndex /// [1,请将您的身份证放在读卡区域内],[2,读卡成功],[3,读卡失败请重新放卡] /// [4,请采集右手拇指指纹],[5,请采集右手无名指指纹],[6,请采集右手中指指纹],[7,请采集右手食指指纹],[8,请采集右手小指指纹] /// [9,请采集左手拇指指纹],[10,请采集左手食指指纹],[11,请采集左手中指指纹],[12,请采集左手无名指指纹],[13,请采集左手小指指纹] /// [14,指纹采集成功],[15,指纹对比成功],[16,请面对摄像头],[17,照片采集成功] /// /// 。输入参数 /// <returns>[1,正确],[0,失败]</returns> [DllImport("HIDSENREPORT.dll", EntryPoint = "SendReport", CharSet = CharSet.Auto, SetLastError = false)] public static extern int CVR_SendReport(int nIndex); #endregion #region 整合类 /// /// 指纹仪初始化,不初始化算法 /// /// <returns>[1,初始化成功],[-1,初始化失败]</returns> public static int HelperZhiWenChuShiHua() { int ret = LIVESCAN_Init(); if (ret == 1) { ret = LIVESCAN_BeginCapture(0); if (ret == 1) { return 1; } else return -1; } else return -1; } /// /// 指纹仪初始化，初始化算法 /// /// <returns>[1,初始化成功],[-1,初始化失败]</returns> public static int HelperZhiWenChuShiHuaAll() { int ret = HelperZhiWenChuShiHua(); if (ret == 1) { ret = FP_Begin(); if (ret == 1) return 1; else return -1; } else return -1; } /// /// 初始化读卡器 /// /// <returns>[1,初始化成功],[-1,初始化失败]</returns> public static int HelperIDCardChuShiHua() { int iPort, iRetUSB = 0, iRetCOM = 0; for (iPort = 1001; iPort <= 1004; iPort++) { iRetUSB = CVR_InitComm(iPort); if (iRetUSB == 1) { break; } } if (iRetUSB != 1) { for (iPort = 1; iPort <= 4; iPort++) { iRetCOM = CVR_InitComm(iPort); if (iRetCOM == 1) { break; } } } if ((iRetCOM == 1) || (iRetUSB == 1)) { return 1; } else { return -1; } } /// /// 读取身份证 /// /// <returns></returns> public static PeopleBean HelperGetPeopleBean() { int authenticate = CVR_Authenticate(); if (authenticate == 1) { int readContent = CVR_Read_FPContent(); if (readContent == 1) { PeopleBean people = new PeopleBean(); HelperSendReport(EnumSendReport.读卡成功); byte[] name = new byte[30]; int length = 30; GetPeopleName(ref name[0], ref length); people.name = Encoding.GetEncoding("GB2312").GetString(name).Replace("\0", "").Trim(); byte[] number = new byte[36]; length = 36; GetPeopleIDCode(ref number[0], ref length); people.number = Encoding.GetEncoding("GB2312").GetString(number).Replace("\0", "").Trim(); byte[] nation = new byte[4]; length = 4; GetPeopleNation(ref nation[0], ref length); people.nation = Encoding.GetEncoding("GB2312").GetString(nation).Replace("\0", "").Trim(); byte[] validtermOfStart = new byte[30]; length = 16; GetStartDate(ref validtermOfStart[0], ref length); people.validtermOfStart = Encoding.GetEncoding("GB2312").GetString(validtermOfStart).Replace("\0", "").Trim(); byte[] birthday = new byte[30]; length = 16; GetPeopleBirthday(ref birthday[0], ref length); people.birthday = Encoding.GetEncoding("GB2312").GetString(birthday).Replace("\0", "").Trim(); byte[] address = new byte[70]; length = 70; GetPeopleAddress(ref address[0], ref length); people.address = Encoding.GetEncoding("GB2312").GetString(address).Replace("\0", "").Trim(); byte[] validtermOfEnd = new byte[30]; length = 16; GetEndDate(ref validtermOfEnd[0], ref length); people.validtermOfEnd = Encoding.GetEncoding("GB2312").GetString(validtermOfEnd).Replace("\0", "").Trim(); byte[] signdate = new byte[30]; length = 30; GetDepartment(ref signdate[0], ref length); people.signdate = Encoding.GetEncoding("GB2312").GetString(signdate).Replace("\0", "").Trim(); byte[] sex = new byte[30]; length = 3; GetPeopleSex(ref sex[0], ref length); people.sex = Encoding.GetEncoding("GB2312").GetString(sex).Replace("\0", "").Trim(); byte[] samid = new byte[32]; CVR_GetSAMID(ref samid[0]); people.samid = Encoding.GetEncoding("GB2312").GetString(samid).Replace("\0", "").Trim(); byte[] ICFeatureData = new byte[1024]; GetFPDate(ref ICFeatureData[0], ref length); people.listFeatureDataBean = new List<ICFeatureDataBean>(); ICFeatureDataBean f1 = new ICFeatureDataBean(); Array.Copy(ICFeatureData, 0, f1.buffer, 0, 512); f1.fileHeadType = ICFeatureData[0]; f1.version = ICFeatureData[1]; f1.collectorCode = ICFeatureData[2]; f1.developerCode = ICFeatureData[3]; f1.registrationResultCode = (EnumRegistrationResult)ICFeatureData[4]; f1.fingerPositionCode = (EnumFingerPosition)ICFeatureData[5]; f1.quality = ICFeatureData[6]; people.listFeatureDataBean.Add(f1); ICFeatureDataBean f2 = new ICFeatureDataBean(); Array.Copy(ICFeatureData, 512, f2.buffer, 0, 512); f2.fileHeadType = ICFeatureData[512]; f2.version = ICFeatureData[513]; f2.developerCode = ICFeatureData[514]; f2.collectorCode = ICFeatureData[515]; f2.registrationResultCode = (EnumRegistrationResult)ICFeatureData[516]; f2.fingerPositionCode = (EnumFingerPosition)ICFeatureData[517]; f2.quality = ICFeatureData[518]; people.listFeatureDataBean.Add(f2); FileStream file = new FileStream(System.Windows.Forms.Application.StartupPath + "\\zp.bmp", FileMode.Open); Image img = Image.FromStream(file); file.Close(); people.photo = img; return people; } else return null; } else return null; } /// /// 获取指纹 /// /// <returns></returns> public static byte[] HelperGetFPRawData() { System.IntPtr pRawData = Marshal.AllocHGlobal(92160); byte[] RawData = new byte[92160]; int ret = LIVESCAN_GetFPRawData(0, pRawData); if (ret == 1) { Marshal.Copy(pRawData, RawData, 0, 92160); Marshal.FreeHGlobal(pRawData); return RawData; } else return null; } /// /// 获取指纹特征 /// /// /// /// <returns></returns> public static ICFeatureDataBean HelperGetFPFeatureExtract(EnumFingerPosition cFingerCode,byte[] buffer) { System.IntPtr pFingerImgBuf1 = Marshal.AllocHGlobal(buffer.Length); Marshal.Copy(buffer, 0, pFingerImgBuf1, buffer.Length); System.IntPtr pFingerFeatureBuf1 = Marshal.AllocHGlobal(512); int ret = FP_FeatureExtract(0, (byte)cFingerCode, pFingerImgBuf1, pFingerFeatureBuf1); if (ret == 1) { byte[] FeatureData = new byte[512]; Marshal.Copy(pFingerFeatureBuf1, FeatureData, 0, 512); Marshal.FreeHGlobal(pFingerImgBuf1); Marshal.FreeHGlobal(pFingerFeatureBuf1); ICFeatureDataBean f1 = new ICFeatureDataBean(); f1.buffer = FeatureData; f1.fileHeadType = f1.buffer[0]; f1.version = f1.buffer[1]; f1.collectorCode = f1.buffer[2]; f1.developerCode = f1.buffer[3]; f1.registrationResultCode = (EnumRegistrationResult)f1.buffer[4]; f1.fingerPositionCode = (EnumFingerPosition)f1.buffer[5]; f1.quality = f1.buffer[6]; return f1; } else { Marshal.FreeHGlobal(pFingerImgBuf1); Marshal.FreeHGlobal(pFingerFeatureBuf1); return null; } } /// /// 获取指纹图像 /// /// /// <returns></returns> public static Bitmap HelperGetFPBitmap(byte[] buffer) { Bitmap bm = new Bitmap(256, 360, PixelFormat.Format8bppIndexed); Rectangle dimension = new Rectangle(0, 0, bm.Width, bm.Height); BitmapData picData = bm.LockBits(dimension, ImageLockMode.ReadWrite, bm.PixelFormat); IntPtr pixelStartAddress = picData.Scan0; System.Runtime.InteropServices.Marshal.Copy(buffer, 0, pixelStartAddress, buffer.Length); bm.UnlockBits(picData); ColorPalette tempPalette; using (Bitmap tempBmp = new Bitmap(1, 1, PixelFormat.Format8bppIndexed)) { tempPalette = tempBmp.Palette; } for (int i = 0; i < 256; i++) { tempPalette.Entries[i] = Color.FromArgb(i, i, i); } bm.Palette = tempPalette; return bm; } /// /// 获取指纹质量 /// /// /// <returns></returns> public static int HelperGetFPQuality(byte[] buffer) { System.IntPtr pFingerImgBuf = Marshal.AllocHGlobal(92160); Marshal.Copy(buffer, 0, pFingerImgBuf, buffer.Length); int sb = 0; int ret = FP_GetQualityScore(pFingerImgBuf, ref sb); if (ret == 1) return sb; else return 0; } /// /// 指纹特征对比 /// /// /// /// <returns></returns> public static float HelperGetFeatureMatch(byte[] buffer1,byte[] buffer2) { System.IntPtr pFingerFeatureBuf1 = Marshal.AllocHGlobal(buffer1.Length); Marshal.Copy(buffer1, 0, pFingerFeatureBuf1, buffer1.Length); System.IntPtr pFingerFeatureBuf2 = Marshal.AllocHGlobal(buffer2.Length); Marshal.Copy(buffer2, 0, pFingerFeatureBuf2, buffer2.Length); float f = 0; int ret = FP_FeatureMatch(pFingerFeatureBuf1, pFingerFeatureBuf2, ref f); Marshal.FreeHGlobal(pFingerFeatureBuf1); Marshal.FreeHGlobal(pFingerFeatureBuf2); return f; } /// /// 关闭 /// public static void Close() { int ret = LIVESCAN_EndCapture(0); ret = FP_End(); } /// /// 发出声音 /// /// public static void HelperSendReport(EnumSendReport sendReport) { CVR_SendReport((int)sendReport); } public static void HelperSendReport(EnumFingerPosition figerPostion) { switch (figerPostion) { case EnumFingerPosition.右手中指: HelperSendReport(EnumSendReport.请采集右手中指指纹); break; case EnumFingerPosition.右手小指: HelperSendReport(EnumSendReport.请采集右手小指指纹); break; case EnumFingerPosition.右手拇指: HelperSendReport(EnumSendReport.请采集右手拇指指纹); break; case EnumFingerPosition.右手环指: HelperSendReport(EnumSendReport.请采集右手无名指指纹); break; case EnumFingerPosition.右手食指: HelperSendReport(EnumSendReport.请采集右手食指指纹); break; case EnumFingerPosition.左手中指: HelperSendReport(EnumSendReport.请采集左手中指指纹); break; case EnumFingerPosition.左手小指: HelperSendReport(EnumSendReport.请采集左手小指指纹); break; case EnumFingerPosition.左手拇指: HelperSendReport(EnumSendReport.请采集左手拇指指纹); break; case EnumFingerPosition.左手环指: HelperSendReport(EnumSendReport.请采集左手无名指指纹); break; case EnumFingerPosition.左手食指: HelperSendReport(EnumSendReport.请采集左手食指指纹); break; } } #endregion #region 附件 /* * * B.4 * 错误代码 [-1,参数错误],[-2,内存分配失败，没有分配到足够的内存],[-3,功能未实现],[-4,设备不存在],[-5,设备未初始化],[-6,非法错误号],[-9,其他错误] * * * */ #endregion } public class PeopleBean { /// /// 姓名 /// public string name { get; set; } /// /// 性别 /// public string sex { get; set; } /// /// 民族 /// public string nation { get; set; } /// /// 出生日期 /// public string birthday { get; set; } /// /// 地址 /// public string address { get; set; } /// /// 身份证号码 /// public string number { get; set; } /// /// 签发机关 /// public string signdate { get; set; } /// /// 起始日期 /// public string validtermOfStart { get; set; } /// /// 截至日期 /// public string validtermOfEnd { get; set; } /// /// 安全模块号 /// public string samid { get; set;} /// /// 指纹 /// public List<ICFeatureDataBean> listFeatureDataBean { get; set; } /// /// 照片 /// public Image photo { get; set; } } /// /// 指纹信息 /// public class ICFeatureDataBean { /// /// 文件头类型 /// public int fileHeadType { get; set; } /// /// 指纹算法版本号 /// public int version { get; set; } /// /// 指纹采集器代码 /// public int collectorCode { get; set; } /// /// 指纹算法开发者代码 /// public int developerCode { get; set; } /// /// 注册结果代码 /// 01H 表示“注册成功”，02H 表示“注册失败”，03H 表示“未注册”，09H 表示“未知” /// public EnumRegistrationResult registrationResultCode { get; set; } /// /// 指位代码 /// [0BH,右手拇指],[0CH,右手食指],[0DH,右手中指],[0EH,右手环指],[0FH,右手小指] /// [10H,左手拇指],[11H,左手食指],[12H,左手中指],[13H,左手环指],[14H,左手小指] /// [61H,右手不确定指位],[62H,左手不确定指位],[63H,其他不确定指位] /// public EnumFingerPosition fingerPositionCode { get; set; } /// /// 质量 /// 值01H表示最低质量，值64H表示最高质量，值00H表示“未知” /// public int quality { get; set; } /// /// 指纹数据 /// public byte[] buffer = new byte[512]; } /// /// 注册结果 /// public enum EnumRegistrationResult : int { 注册成功=1, 注册失败=2, 未注册=3, 未知=9, } /// /// 指位 /// public enum EnumFingerPosition :int { 右手拇指=11, 右手食指=12, 右手中指=13, 右手环指=14, 右手小指=15, 左手拇指=16, 左手食指=17, 左手中指=18, 左手环指=19, 左手小指=20, 右手不确定指位=97, 左手不确定指位=98, 其他不确定指位=99, } /// /// 声音 /// public enum EnumSendReport :int { 请将您的身份证放在读卡区域内=1, 读卡成功=2, 读卡失败请重新放卡=3, 请采集右手拇指指纹=4, 请采集右手无名指指纹=5, 请采集右手中指指纹=6, 请采集右手食指指纹=7, 请采集右手小指指纹=8, 请采集左手拇指指纹=9, 请采集左手食指指纹=10, 请采集左手中指指纹=11, 请采集左手无名指指纹=12, 请采集左手小指指纹=13, 指纹采集成功=14, 指纹对比成功=15, 请面对摄像头=16, 照片采集成功=17, } }
using System; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; namespace Helper { public class ViKeyAPI { public const string DefaultUserPassword = "11111111"; public const string DefaultAdminPassword = "00000000"; // 错误代码 public const long VIKEY_SUCCESS = 0x00000000; //成功 public const long VIKEY_ERROR_NO_VIKEY = 0x80000001; //没有找到ViKey加密锁 public const long VIKEY_ERROR_INVALID_PASSWORD = 0x80000002; //密码错误 public const long VIKEY_ERROR_NEED_FIND = 0x80000003; //请先查找加密锁 public const long VIKEY_ERROR_INVALID_INDEX = 0x80000004; //无效的句柄 public const long VIKEY_ERROR_INVALID_VALUE = 0x80000005; //数值错误 public const long VIKEY_ERROR_INVALID_KEY = 0x80000006; //秘钥无效 public const long VIKEY_ERROR_GET_VALUE = 0x80000007; //读取信息错误 public const long VIKEY_ERROR_SET_VALUE = 0x80000008; //设置信息错误 public const long VIKEY_ERROR_NO_CHANCE = 0x80000009; //没有机会 public const long VIKEY_ERROR_NO_TAUTHORITY = 0x8000000A; //权限不足 public const long VIKEY_ERROR_INVALID_ADDR_OR_SIZE = 0x8000000B; //地址或长度错误 public const long VIKEY_ERROR_RANDOM = 0x8000000C; //获取随机数错误 public const long VIKEY_ERROR_SEED = 0x8000000D; //获取种子错误 public const long VIKEY_ERROR_CONNECTION = 0x8000000E; //通信错误 public const long VIKEY_ERROR_CALCULATE = 0x8000000F; //算法或计算错误 public const long VIKEY_ERROR_MODULE = 0x80000010; //计数器错误 public const long VIKEY_ERROR_GENERATE_NEW_PASSWORD = 0x80000011; //产生密码错误 public const long VIKEY_ERROR_ENCRYPT_FAILED = 0x80000012; //加密数据错误 public const long VIKEY_ERROR_DECRYPT_FAILED = 0x80000013; //解密数据错误 public const long VIKEY_ERROR_ALREADY_LOCKED = 0x80000014; //ViKey加密锁已经被锁定 public const long VIKEY_ERROR_UNKNOWN_COMMAND = 0x80000015; //无效的命令 public const long VIKEY_ERROR_UNKNOWN_ERROR = 0xFFFFFFFF; //未知错误 //ViKey加密狗类型 VikeyGetType返回值代表的类型 public const uint ViKeyAPP = 0; //实用型加密狗ViKeyAPP public const uint ViKeySTD = 1; //标准型加密狗ViKeySTD public const uint ViKeyNET = 2; //网络型加密狗ViKeyNET public const uint ViKeyPRO = 3; //专业型加密狗ViKeyPRO public const uint ViKeyWEB = 4; //身份认证型加密狗ViKeyWEB public const uint ViKeyTIME = 5; //时间型加密狗ViKeyTIME #region 翻译 /// /// 返回加密狗类型 /// /// /// <returns></returns> public static string GetTypeName(uint res) { if (res == ViKeyAPP) return "ViKeyApp"; else if (res == ViKeySTD) return "ViKeySTD"; else if (res == ViKeyNET) return "ViKeyNET"; else if (res == ViKeyPRO) return "ViKeyPRO"; else if (res == ViKeyWEB) return "VikeyWEB"; else if (res == ViKeyTIME) return "VikeyTIME"; else return "未知"; } /// /// 获取错误信息 /// /// /// <returns></returns> public static string GetErrorMsg(uint res) { if (res == VIKEY_SUCCESS) return "成功！"; else if (res == VIKEY_ERROR_NO_VIKEY) return "没有找到ViKey加密锁"; else if (res == VIKEY_ERROR_INVALID_PASSWORD) return "密码错误"; else if (res == VIKEY_ERROR_NEED_FIND) return "请先查找加密锁"; else if (res == VIKEY_ERROR_INVALID_INDEX) return "无效的句柄"; else if (res == VIKEY_ERROR_INVALID_VALUE) return "数值错误"; else if (res == VIKEY_ERROR_INVALID_KEY) return "秘钥无效"; else if (res == VIKEY_ERROR_GET_VALUE) return "读取信息错误"; else if (res == VIKEY_ERROR_SET_VALUE) return "设置信息错误"; else if (res == VIKEY_ERROR_NO_CHANCE) return "没有机会"; else if (res == VIKEY_ERROR_NO_TAUTHORITY) return "权限不足"; else if (res == VIKEY_ERROR_INVALID_ADDR_OR_SIZE) return "地址或长度错误"; else if (res == VIKEY_ERROR_RANDOM) return "获取随机数错误"; else if (res == VIKEY_ERROR_SEED) return "获取种子错误"; else if (res == VIKEY_ERROR_CONNECTION) return "通信错误"; else if (res == VIKEY_ERROR_CALCULATE) return "算法或计算错误"; else if (res == VIKEY_ERROR_MODULE) return "计数器错误"; else if (res == VIKEY_ERROR_GENERATE_NEW_PASSWORD) return "产生密码错误"; else if (res == VIKEY_ERROR_ENCRYPT_FAILED) return "加密数据错误"; else if (res == VIKEY_ERROR_DECRYPT_FAILED) return "解密数据错误"; else if (res == VIKEY_ERROR_ALREADY_LOCKED) return "加密锁已经被锁定"; else if (res == VIKEY_ERROR_UNKNOWN_COMMAND) return "无效的命令"; else if (res == VIKEY_ERROR_UNKNOWN_ERROR) return "未知错误"; else return "未知！"; } #endregion #region 查找加密狗 // 函数引用声明 /// /// 查找系统中的ViKey加密狗 /// 【注意】：程序访问ViKey加密狗前，必须先调用此函数，调用一次就可以。 /// /// 如果查找到系统中存在加密狗，返回查找到加密狗的个数 /// <returns>0：表示系统中存在ViKey加密狗 非0：表示系统中没有找到ViKey加密狗</returns> [DllImport("ViKey")] public static extern uint VikeyFind(ref uint pdwCount); #endregion #region 登录注销加密狗 /// /// 用户登陆加密狗，登陆成功后，加密狗的当前权限为用户权限。可以调用VikeyGetLevel获取加密狗的当前权限。 /// /// 【输入】指定加密狗的序号 比如，一共插了2个加密狗，Index=0表示操作第一个加密狗，Index=1表示操作第二个加密狗 /// 【返回】加密狗的用户密码， 8个字母或数字 /// <returns>0：表示函数执行成功 非0：则表示函数失败，错误原因可以参见错误码含义 </returns> [DllImport("ViKey")] public static extern uint VikeyUserLogin(ushort Index, Byte[] pUserPassword); /// /// 管理员登陆加密狗，登陆成功后，加密狗的当前权限为管理员权限。可以调用VikeyGetLevel获取加密狗的当前权限。 /// /// 【输入】指定加密狗的序号 比如，一共插了2个加密狗，Index=0表示操作第一个加密狗，Index=1表示操作第二个加密狗 /// 【返回】加密狗的管理员密码， 8个字母或数字 /// <returns>0：表示函数执行成功 非0：则表示函数失败，错误原因可以参见错误码含义 </returns> [DllImport("ViKey")] public static extern uint VikeyAdminLogin(ushort Index, Byte[] pAdminPassword); /// /// 登出(关闭)加密狗，调用该函数过后，加密狗的当前权限将变为匿名权限。 /// 当程序不需要对加密狗进行操作时候，调用此函数关闭加密狗，以免其他误操作或者恶意程序对加密狗内部信息进行窃取。 /// /// 【输入】指定加密狗的序号 比如，一共插了2个加密狗，Index=0表示操作第一个加密狗，Index=1表示操作第二个加密狗 /// <returns>0：表示函数执行成功 非0：则表示函数失败，错误原因可以参见错误码含义</returns> [DllImport("ViKey")] public static extern uint VikeyLogoff(ushort Index); #endregion #region 读写加密狗的基本信息 /// /// 获取ViKey加密狗的硬件ID /// 长度为4个字节 /// 一个DWORD /// 该硬件ID为ViKey加密狗的唯一标识，类似于人的身份证号码. /// 全球唯一，每个加密狗的都有一个全球唯一的硬件ID. /// /// 【输入】指定加密狗的序号 比如，一共插了2个加密狗，Index=0表示操作第一个加密狗，Index=1表示操作第二个加密狗 /// 【返回】返回ViKey加密狗的硬件ID /// <returns>0：表示函数执行成功 非0：则表示函数失败，错误原因可以参见错误码含义</returns> [DllImport("ViKey")] public static extern uint VikeyGetHID(ushort Index, ref uint pdwHID); /// /// 获取ViKey加密狗的类型。ViKey系列加密狗有很多种类型，可以调用此函数获取当前加密狗的类型。 /// 0 - ViKeyAPP 实用狗 /// 1 - ViKeySTD 标准狗 /// 2 - ViKeyNET 网络狗 /// 3 - ViKeyPRO 专业狗 /// 4 - ViKeyWEB 身份认证狗 /// 5 - ViKeyTIME 时间狗 /// /// 【输入】指定加密狗的序号 比如，一共插了2个加密狗，Index=0表示操作第一个加密狗，Index=1表示操作第二个加密狗 /// 【返回】返回加密狗的产品类型 /// <returns>0：表示函数执行成功 非0：则表示函数失败，错误原因可以参见错误码含义 </returns> [DllImport("ViKey")] public static extern uint VikeyGetType(ushort Index, ref uint pType); /// /// 获取ViKey加密狗的当前权限，ViKey加密狗有三级权限，匿名权限、用户权限、管理员权限 /// 用户登陆(VikeyUserLogin)成功后加密狗的权限自动变为用户权限。 /// 管理员登陆(VikeyAdminLogin)成功后加密狗的权限自动变为管理员权限。 /// 每种权限可以对加密狗的操作均有限制，比如说用户权限，只能对数据区进行读取，不可写入，管理员权限对所有数据均有读写权限。 /// 0 - 匿名权限 /// 1 - 用户权限 /// 2 - 管理员权限 /// /// 【输入】指定加密狗的序号 比如，一共插了2个加密狗，Index=0表示操作第一个加密狗，Index=1表示操作第二个加密狗 /// 【返回】返回雄狮加密狗的当前权限 /// <returns>0：表示函数执行成功 非0：则表示函数失败，错误原因可以参见错误码含义</returns> [DllImport("ViKey")] public static extern uint VikeyGetLevel(ushort Index, ref Byte pLevel); /// /// 设置ViKey加密狗的设备名称，长度为16个字符或8个汉字，字母或数字 /// /// 【输入】指定加密狗的序号 比如，一共插了2个加密狗，Index=0表示操作第一个加密狗，Index=1表示操作第二个加密狗 /// 【返回】ViKey加密狗的设备名称 /// <returns>0：表示函数执行成功 非0：则表示函数失败，错误原因可以参见错误码含义</returns> [DllImport("ViKey")] public static extern uint VikeySetPtroductName(ushort Index, Byte[] szName); /// /// 获取ViKey加密狗的设备名称，长度为16个字符或8个汉字，字母或数字 /// 【注意】：此函数需要管理员权限，也就是说调用该函数前必须保证加密狗当前权限为管理员权限。 /// /// 【输入】指定加密狗的序号 比如，一共插了2个加密狗，Index=0表示操作第一个加密狗，Index=1表示操作第二个加密狗 /// 【返回】ViKey加密狗的设备名称 /// <returns>0：表示函数执行成功 非0：则表示函数失败，错误原因可以参见错误码含义</returns> [DllImport("ViKey")] public static extern uint VikeyGetPtroductName(ushort Index, Byte[] szName); /// /// 设置加密狗的用户密码错误尝试次数，例如设置用户密码错误尝试次数为5，当执行用户登陆时候，如果连续 /// 输入5次错误的密码，加密狗将被锁定，以后将不能登陆。该机制类似于银行卡密码，连续输入3次错误密码，银行卡将被 /// 锁定。有效防止暴力破解、穷举密码的方式破解密码。 /// 【注意】：此函数需要管理员权限，也就是说调用该函数前必须保证加密狗当前权限为管理员权限。 /// /// 【输入】指定加密狗的序号 比如，一共插了2个加密狗，Index=0表示操作第一个加密狗，Index=1表示操作第二个加密狗 /// 【输入】错误密码尝试次数 0：不做限制 非0：限制为指定次数 /// <returns>0：表示函数执行成功 非0：则表示函数失败，错误原因可以参见错误码含义</returns> [DllImport("ViKey")] public static extern uint VikeySetUserPassWordAttempt(ushort Index, Byte cAttempt); /// /// 设置加密狗的管理员密码错误尝试次数，例如设置管理员密码错误尝试次数为5，当执行管理员登陆时候，如果连续 /// 输入5次错误的密码，加密狗将被锁定，以后将不能登陆。该机制类似于银行卡密码，连续输入3次错误密码，银行卡将被 /// 锁定。有效防止暴力破解、穷举密码的方式破解密码。 /// 【注意】：此函数需要管理员权限，也就是说调用该函数前必须保证加密狗当前权限为管理员权限。 /// /// 【输入】指定加密狗的序号 比如，一共插了2个加密狗，Index=0表示操作第一个加密狗，Index=1表示操作第二个加密狗 /// 【输入】错误密码尝试次数 0：不做限制 非0：限制为指定次数 /// <returns>0：表示函数执行成功 非0：则表示函数失败，错误原因可以参见错误码含义</returns> [DllImport("ViKey")] public static extern uint VikeySetAdminPassWordAttempt(ushort Index, Byte cAttempt); /// /// 获取加密狗的用户密码错误尝试次数，例如设置用户密码错误尝试次数为5，当执行用户登陆时候，如果连续 /// 输入5次错误的密码，加密狗将被锁定，不能登陆。该机制类似于银行卡密码，连续输入3次错误密码，银行卡将被 /// 锁定。有效防止暴力破解。 /// /// 【输入】指定加密狗的序号 /// 【返回】当前剩余的密码尝试次数 /// 【返回】最大密码尝试次数，该次数为通过VikeySetUserPassWordAttempt设置的次数 /// <returns>0：表示函数执行成功 非0：则表示函数失败，错误原因可以参见错误码含义</returns> [DllImport("ViKey")] public static extern uint VikeyGetUserPassWordAttempt(ushort Index, Byte pcCurrentAttempt, Byte pcMaxAttempt); /// /// 获取加密狗的管理员密码错误尝试次数，例如设置管理员密码错误尝试次数为5，当执行管理员登陆时候，如果连续 /// 输入5次错误的密码，加密狗将被锁定，不能登陆。该机制类似于银行卡密码，连续输入3次错误密码，银行卡将被 /// 锁定。有效防止暴力破解。 /// /// 【输入】指定加密狗的序号 /// 【返回】当前剩余的密码尝试次数 /// 【返回】最大密码尝试次数，该次数为通过VikeySetAdminPassWordAttempt设置的次数 /// <returns>0：表示函数执行成功 非0：则表示函数失败，错误原因可以参见错误码含义</returns> [DllImport("ViKey")] public static extern uint VikeyGetAdminPassWordAttempt(ushort Index, Byte pcCurrentAttempt, Byte pcMaxAttempt); #endregion #region 重置加密狗密码 /// /// 修改ViKey加密狗的用户密码和管理员 /// 【注意】：此函数需要管理员权限，也就是说调用该函数前必须保证加密狗当前权限为管理员权限，才能修改成功。 /// /// 【输入】指定加密狗的序号 /// 【输入】加密狗新的用户密码 /// 【输入】加密狗新的管理员密码 /// <returns>0：表示函数执行成功 非0：则表示函数失败，错误原因可以参见错误码含义</returns> [DllImport("ViKey")] public static extern uint VikeyResetPassword(ushort Index, Byte[] pNewUserPassword, Byte[] pNewAdminPassword); #endregion #region 获取随机数 /// /// 获取4个随机数，在程序中程序员可能需要到随机数，可以调用加密狗的该函数获取加密狗中的随机数，更为安全。 /// /// 【输入】指定加密狗的序号 /// 【返回】获取随机数1（0~65535） /// 【返回】获取随机数2（0~65535） /// 【返回】获取随机数3（0~65535） /// 【返回】获取随机数4（0~65535） /// <returns>0：表示函数执行成功 非0：则表示函数失败，错误原因可以参见错误码含义</returns> [DllImport("ViKey")] public static extern uint ViKeyRandom(ushort Index, ref ushort pReturn1, ref ushort pReturn2, ref ushort pReturn3, ref ushort pReturn4); #endregion #region 数据读写 /// /// 设置加密狗的软件ID /// 【注意】：此函数需要管理员权限，也就是说调用该函数前必须保证加密狗当前权限为管理员权限。 /// /// 【输入】指定加密狗的序号 /// 【输入】加密狗的软件ID标识， 8个字母或数字 /// <returns>0：表示函数执行成功 非0：则表示函数失败，错误原因可以参见错误码含义</returns> [DllImport("ViKey")] public static extern uint VikeySetSoftIDString(ushort Index, Byte[] SoftIDString); /// /// 获取加密狗的软件ID /// /// 【输入】指定加密狗的序号 /// 【返回】加密狗的软件ID标识， 8个字母或数字 /// <returns>0：表示函数执行成功 非0：则表示函数失败，错误原因可以参见错误码含义</returns> [DllImport("ViKey")] public static extern uint VikeyGetSoftIDString(ushort Index, Byte[] SoftIDString); /// /// 读取加密狗的数据，加密狗有数据存储区，可供读写 /// 【注意】：此函数需要用户权限，也就是说调用该函数前必须保证加密狗当前权限要大于用户权限。 /// /// 【输入】指定加密狗的序号 /// 【输入】读取数据的起始地址 /// 【输入】读取数据的长度 /// 【返回】读取到的数据 /// <returns>0：表示函数执行成功 非0：则表示函数失败，错误原因可以参见错误码含义</returns> [DllImport("ViKey")] public static extern uint VikeyReadData(ushort Index, ushort pStartAddress, ushort pBufferLength, Byte[] pBuffer); /// /// 写入数据到加密狗，加密狗有数据存储区，可供读写 /// 【注意】：此函数需要管理员权限，也就是说调用该函数前必须保证加密狗当前权限为管理员权限。 /// /// 【输入】指定加密狗的序号 /// 【输入】写入数据的起始地址 /// 【输入】写入数据的长度 /// 【返回】写入数据的指针 /// <returns>0：表示函数执行成功 非0：则表示函数失败，错误原因可以参见错误码含义</returns> [DllImport("ViKey")] public static extern uint VikeyWriteData(ushort Index, ushort pStartAddress, ushort pBufferLength, Byte[] pBuffer); #endregion #region 计数器模块 /// /// 将指定计数器中的数值减一 /// ViKey加密狗为程序员提供一组计数器，该计数器只能递减，也就是递减计数器，可以设置初始值，调用该函数来实现减一。 /// 【注意】：此函数需要用户权限，也就是说调用该函数前必须保证加密狗当前权限为用户权限，方可调用成功。 /// /// 【输入】指定加密狗的序号 /// 【输入】计数器的序号 /// <returns>0：表示函数执行成功 非0：则表示函数失败，错误原因可以参见错误码含义</returns> [DllImport("ViKey")] public static extern uint ViKeyDecraseModule(ushort Index, ushort ModelueIndex); /// /// 获取加密狗中计数器的值 /// ViKey加密狗为程序员提供一组计数器，该计数器只能递减，也就是递减计数器，可以设置初始值，调用该函数来获取计数器中的数值。 /// 【注意】：此函数需要用户权限，也就是说调用该函数前必须保证加密狗当前权限为用户权限，方可调用成功。 /// /// 【输入】指定加密狗的序号 /// 【输入】计数器的序号 /// 【返回】计数器中的值 /// <returns>0：表示函数执行成功 非0：则表示函数失败，错误原因可以参见错误码含义</returns> [DllImport("ViKey")] public static extern uint ViKeyGetModule(ushort Index, ushort wModuleIndex, ushort pwValue); /// /// 设置递减计数器的初始值和模式 /// ViKey加密狗为程序员提供一组计数器，该计数器只能递减，也就是递减计数器，调用该函数来设置计数值的初始状态。 /// 【注意】：此函数需要管理员权限，也就是说调用该函数前必须保证加密狗当前权限为管理员权限。 /// /// 【输入】指定加密狗的序号 /// 【输入】计数器的序号 /// 【输入】计数器的值 /// 【输入】计数器的模式 1：允许递减 0：不允许递减 /// <returns>0：表示函数执行成功 非0：则表示函数失败，错误原因可以参见错误码含义</returns> [DllImport("ViKey")] public static extern uint ViKeySetModule(ushort Index, ushort ModelueIndex, ushort pValue, ushort pDecrease); /// /// 检查计数器的数值是否为零 模式是否允许可以递减 /// ViKey加密狗为程序员提供一组计数器，该计数器只能递减，也就是递减计数器，调用该函数来检查计数器中的数值是否为0。 /// 【注意】：此函数需要用户权限，也就是说调用该函数前必须保证加密狗当前权限为用户权限，方可调用成功。 /// /// 【输入】指定加密狗的序号 /// 【输入】计数器的序号 /// 【输入】是否为零 /// 【输入】是否允许递减 /// <returns>0：表示函数执行成功 非0：则表示函数失败，错误原因可以参见错误码含义</returns> [DllImport("ViKey")] public static extern uint ViKeyCheckModule(ushort Index, ushort ModelueIndex, ref ushort pIsZero, ref ushort pCanDecrase); #endregion #region 加解密算法 /// /// 设置DES算法用到的秘钥Key，Des加解密算法是一种国际标准的加解密算法，安全性高，破解难度大. /// 【注意】：此函数需要管理员权限，也就是说调用该函数前必须保证加密狗当前权限为管理员权限。 /// /// 【输入】指定加密狗的序号 /// 【输入】秘钥地址，秘钥长度固定为8个字节 /// <returns>0：表示函数执行成功 非0：则表示函数失败，错误原因可以参见错误码含义</returns> [DllImport("ViKey")] public static extern uint VikeyDesSetKey(ushort Index, Byte[] pMD5key); /// /// DES加密数据，加密长度必须为8的倍数 /// /// 【输入】指定加密狗的序号 /// 【输入】要加密的数据长度，明文当长度必须为8的倍数 /// 【输入】明文地址 /// 【返回】加密返回密文地址 /// <returns>0：表示函数执行成功 非0：则表示函数失败，错误原因可以参见错误码含义</returns> [DllImport("ViKey")] public static extern uint VikeyDesEncrypt(ushort Index, ushort length, Byte[] pText, Byte[] pResult); /// /// DES解密数据，解密长度必须为8的倍数 /// /// 【输入】指定加密狗的序号 /// 【输入】要解密的数据长度，明文当长度必须为8的倍数 /// 【输入】密文地址 /// 【返回】解密返回明文地址 /// <returns>0：表示函数执行成功 非0：则表示函数失败，错误原因可以参见错误码含义</returns> [DllImport("ViKey")] public static extern uint VikeyDesDecrypt(ushort Index, ushort length, Byte[] pText, Byte[] pResult); /// /// 设置3DES算法用到的秘钥Key，3Des加解密算法是一种国际标准的加解密算法，安全性高，破解难度大. /// 【注意】：此函数需要管理员权限，也就是说调用该函数前必须保证加密狗当前权限为管理员权限。 /// /// 【输入】指定加密狗的序号 /// 【输入】秘钥地址 /// 【输入】0表示密钥长度为16字节 1表示密钥长度为24字节 /// <returns>0：表示函数执行成功 非0：则表示函数失败，错误原因可以参见错误码含义</returns> [DllImport("ViKey")] public static extern uint Vikey3DesSetKey(ushort Index, Byte[] pMD5key, ushort keyType); /// /// 3DES加密数据，向量为0，ECB模式 ，加密长度必须为8的倍数 /// /// 【输入】指定加密狗的序号 /// 【输入】要加密的数据长度，明文当长度必须为8的倍数 /// 【输入】明文地址 /// 【返回】加密返回密文地址 /// <returns>0：表示函数执行成功 非0：则表示函数失败，错误原因可以参见错误码含义</returns> [DllImport("ViKey")] public static extern uint Vikey3DesEncrypt(ushort Index, ushort length, Byte[] pText, Byte[] pResult); /// /// 3DES解密数据，向量为0，ECB模式 ，解密长度必须为8的倍数 /// /// 【输入】指定加密狗的序号 /// 【输入】要解密的数据长度，明文当长度必须为8的倍数 /// 【输入】密文地址 /// 【返回】解密返回明文地址 /// <returns>0：表示函数执行成功 非0：则表示函数失败，错误原因可以参见错误码含义</returns> [DllImport("ViKey")] public static extern uint Vikey3DesDecrypt(ushort Index, ushort length, Byte[] pText, Byte[] pResult); #endregion #region 哈希认证算法 /// /// 进行MD5哈希运算 /// /// 【输入】指定加密狗的序号 /// 【输入】数据长度 /// 【输入】数据内容 /// 【返回】哈希运算结果 /// <returns>0：表示函数执行成功 非0：则表示函数失败，错误原因可以参见错误码含义</returns> [DllImport("ViKey")] public static extern uint VikeyMD5(ushort Index, ushort length, Byte[] pText, Byte[] pResult); /// /// 设置MD5算法秘钥 /// 【注意】：此函数需要管理员权限，也就是说调用该函数前必须保证加密狗当前权限为管理员权限。 /// /// 【输入】指定加密狗的序号 /// 【输入】秘钥内容 /// <returns>0：表示函数执行成功 非0：则表示函数失败，错误原因可以参见错误码含义</returns> [DllImport("ViKey")] public static extern uint VikeySetMD5Key(ushort Index, Byte[] pMD5key); /// /// 进行HMAC_MD5哈希运算 /// 【注意】：此函数需要用户权限，也就是说调用该函数前必须保证加密狗当前权限为用户权限，方可调用成功。 /// /// 【输入】指定加密狗的序号 /// 【输入】输入内容长度 /// 【输入】输入内容 /// 【返回】计算结果 /// <returns>0：表示函数执行成功 非0：则表示函数失败，错误原因可以参见错误码含义</returns> [DllImport("ViKey")] public static extern uint VikeyHmacMD5(ushort Index, ushort length, Byte[] pText, Byte[] pResult); /// /// 进行SHA1哈希运算 /// /// 【输入】指定加密狗的序号 /// 【输入】数据长度 /// 【输入】数据内容 /// 【返回】哈希运算结果 /// <returns>0：表示函数执行成功 非0：则表示函数失败，错误原因可以参见错误码含义</returns> [DllImport("ViKey")] public static extern uint VikeySHA1(ushort Index, ushort length, Byte[] pText, Byte[] pResult); /// /// 设置SHA1算法秘钥 /// 【注意】：此函数需要管理员权限，也就是说调用该函数前必须保证加密狗当前权限为管理员权限。 /// /// 【输入】指定加密狗的序号 /// 【输入】秘钥内容 /// <returns>0：表示函数执行成功 非0：则表示函数失败，错误原因可以参见错误码含义</returns> [DllImport("ViKey")] public static extern uint VikeySetSHA1Key(ushort Index, Byte[] pSHA1key); /// /// 进行HMAC_SHA1哈希运算 /// 【注意】：此函数需要用户权限，也就是说调用该函数前必须保证加密狗当前权限为用户权限，方可调用成功。 /// /// 【输入】指定加密狗的序号 /// 【输入】输入内容长度 /// 【输入】输入内容 /// 【返回】计算结果 /// <returns>0：表示函数执行成功 非0：则表示函数失败，错误原因可以参见错误码含义</returns> [DllImport("ViKey")] public static extern uint VikeyHmacSHA1(ushort Index, ushort length, Byte[] pText, Byte[] pResult); #endregion #region 时钟功能 /// /// ViKeyTime时钟型加密狗，内部有独立的电子时钟，可以简单的理解为内部有个和人们带的电子表一样，可以实时获取当前 /// 日期、时间，但是这个日期、时间无法被篡改。该函数就是获取加密狗内部时钟的时间。 /// typedef struct _VIKEY_TIME ///{ /// BYTE cYear; /// BYTE cMonth; /// BYTE cDay; /// BYTE cHour; /// BYTE cMinute; /// BYTE cSecond; ///} SVikeyTime, *PVIKEYTIME; /// /// 【输入】指定加密狗的序号 /// 【返回】当前日期、时间，6个字节内容分别是年月日时分秒 /// <returns>0：表示函数执行成功 非0：则表示函数失败，错误原因可以参见错误码含义</returns> [DllImport("ViKey")] public static extern uint VikeyGetTime(ushort Index, Byte[] pTime); #endregion #region 网络功能 /// /// 设置网络狗允许连接的最大客户端数，该函数只针对ViKeyNET网络狗有效 /// 【注意】：此函数需要管理员权限，也就是说调用该函数前必须保证加密狗当前权限为管理员权限。 /// /// 【输入】指定加密狗的序号 /// 【输入】网络狗允许连接的最大客户端数 /// <returns>0：表示函数执行成功 非0：则表示函数失败，错误原因可以参见错误码含义</returns> [DllImport("ViKey")] public static extern uint VikeySetMaxClientCount(ushort Index, ushort dwCount); /// /// 获取网络狗允许连接的最大客户端数，该函数只针对ViKeyNET网络狗有效 /// 【注意】：此函数需要用户权限，也就是说调用该函数前必须保证加密狗当前权限为用户权限，方可调用成功。 /// /// 【输入】指定加密狗的序号 /// 【返回】网络狗允许连接的最大客户端数 /// <returns>0：表示函数执行成功 非0：则表示函数失败，错误原因可以参见错误码含义</returns> [DllImport("ViKey")] public static extern uint VikeyGetMaxClientCount(ushort Index, ushort pdwCount); #endregion #region 自动打开网页 /// /// 在网页应用中，安装加密狗控件后，通过此接口设置自动打开网页的网址 /// 【注意】：此函数需要管理员权限，也就是说调用该函数前必须保证加密狗当前权限为管理员权限。 /// /// 【输入】指定加密狗的序号 /// 【输入】自动打开网页的网址，以零结尾的字符串 /// <returns>0：表示函数执行成功 非0：则表示函数失败，错误原因可以参见错误码含义</returns> [DllImport("ViKey")] public static extern uint VikeySetAutoRunUrl(ushort Index, Byte[] pUrl); /// /// 通过此接口获取自动打开网页的网址 /// /// 【输入】指定加密狗的序号 /// 【返回】自动打开网页的网址 /// <returns>0：表示函数执行成功 非0：则表示函数失败，错误原因可以参见错误码含义</returns> [DllImport("ViKey")] public static extern uint VikeyGetAutoRunUrl(ushort Index, Byte[] pUrl); #endregion [DllImport("ViKey")] public static extern uint VikeySeed(ushort Index, ref uint pSeed, ref ushort pReturn1, ref ushort pReturn2, ref ushort pReturn3, ref ushort pReturn4); public static byte[] intToBytes(int value) { byte[] src = new byte[4]; src[0] = (byte)((value >> 24) & 0xFF); src[1] = (byte)((value >> 16) & 0xFF); src[2] = (byte)((value >> 8) & 0xFF); src[3] = (byte)(value & 0xFF); return src; } public static int bytesToInt(byte[] src, int offset) { int value; value = (int)(((src[offset] & 0xFF) << 24) | ((src[offset + 1] & 0xFF) << 16) | ((src[offset + 2] & 0xFF) << 8) | (src[offset + 3] & 0xFF)); return value; } } }
using System; using System.Collections.Generic; using System.Text; using System.Runtime.InteropServices; namespace API { public static class ET99_API { #region 常量 /// /// 函数执行成功 /// public const int ET_SUCCESS = 0x00; /// /// 访问被拒绝，权限不够 /// public const int ET_ACCESS_DENY = 0x01; /// /// 通讯错误，没有打开设备 /// public const int ET_COMMUNICATIONS_ERROR = 0x02; /// /// 无效的参数，参数出错 /// public const int ET_INVALID_PARAMETER = 0x03; /// /// 没有设置 PID /// public const int ET_NOT_SET_PID = 0x04; /// /// 打开指定的设备失败 /// public const int ET_UNIT_NOT_FOUND = 0x05; /// /// 硬件错误 /// public const int ET_HARD_ERROR = 0x06; /// /// 未知错误 /// public const int ET_UNKNOWN_ERROR = 0x07; /// /// 验证 PIN码掩码 /// public const int ET_PIN_ERR_MASK = 0x0F; /// /// 验证 PIN码,设备被锁定 /// public const int ET_PIN_ERR_LOCKED = 0xF0; /// /// 验证 PIN码错误且永远不锁死 /// public const int ET_PIN_ERR_MAX = 0xFF; /// /// 表示验证普通用户 pin /// public const int ET_VERIFY_USERPIN = 0; /// /// 表示验证超级用户 pin /// public const int ET_VERIFY_SOPIN = 1; /// /// 表示数据区可读写 /// public const int ET_USER_WRITE_READ = 0; /// /// 表示数据区只允许读 /// public const int ET_USER_READ_ONLY = 1; /// /// 常量 PID,默认的产品PID /// public const string CONST_PID = "ffffffff"; #endregion /// /// 根据错误码显示错误提示内容 /// /// public static string ShowResultText(uint result) { switch (result) { case (ET_SUCCESS): { return "操作成功！"; } case (ET_ACCESS_DENY): { return "访问被拒绝，权限不够！"; } case (ET_COMMUNICATIONS_ERROR): { return "通讯错误，没有打开设备 ！"; } case (ET_INVALID_PARAMETER): { return "无效的参数，参数出错 ！"; } case (ET_NOT_SET_PID): { return "没有设置 PID ！"; } case (ET_UNIT_NOT_FOUND): { return "打开指定的设备失败！"; } case (ET_HARD_ERROR): { return "硬件错误！"; } case (ET_UNKNOWN_ERROR): { return "未知错误！"; } case (ET_PIN_ERR_MAX): { return "PIN码错误！请核实。"; } case (ET_PIN_ERR_LOCKED): { return "PIN码错误！设备已经被锁死。"; } } //输出剩余PIN验证次数 if (result > ET_PIN_ERR_LOCKED && result < ET_PIN_ERR_MAX) { return "PIN码验证错误！剩余重试次数：" + (result - ET_PIN_ERR_LOCKED).ToString(); } return "未知代码！"; } /// /// 查找计算机上指定 pid 的 ET99 个数。 /// /// [in]产品标识, 为固定长度 8 个字节的字符串； /// [out]还回的设备个数； /// <returns></returns> [DllImport("FT_ET99_API.dll")] public static extern uint et_FindToken(byte[] pid, out int count); /// /// 打开指定 PID的硬件,由 index 指定打开硬件的索引， index 应该小于等于找到的 Token 数目。进入匿名用户状态。 /// /// [out]打开设备的句柄，返回给用户，供以后的函数调用； /// [in]输入的硬件设备的 pid, 为固定长度 8 个字节的字符串； /// [in]打开第 index 个硬件设备。 /// <returns>ET_SUCCESS：执行成功。 ET_UNIT_NOT_FOUND：打开指定的设备失败。</returns> [DllImport("FT_ET99_API.dll")] public static extern uint et_OpenToken(ref IntPtr hHandle, byte[] pid, int index); /// /// 关闭指定的设备。 /// /// [in] 设备句柄。 /// <returns>ET_SUCCESS：关闭成功。 ET_COMMUNICATIONS_ERROR：没有打开设备。</returns> [DllImport("FT_ET99_API.dll")] public static extern uint et_CloseToken(IntPtr hHandle); /// /// 从指定的位置，读取指定的数据到指定的 BUFFER 中。此函数调用需要有User权限，且调用以后不改变安全状态。 /// /// ：[in]设备句柄 /// [in]偏移量 /// [in]长度，不能超过 60，如果超过则需要读多次。 /// [out]读出的数据存放此缓存区中，调用者保证缓冲区大小至少是 Len，否则可能产生系统存取异常。 /// <returns>第二章 API接口函数 ET_COMMUNICATIONS_ERROR：没有打开设备。ET_SUCCESS：表示成功。 ET_INVALID_PARAMETER：无效的参数。 ET_NOT_SET_PID：没有设置 PID。 ET_ACCESS_DENY：权限不够。 </returns> [DllImport("FT_ET99_API.dll")] public static extern uint et_Read(IntPtr hHandle, ushort offset, int len, byte[] pucReadBuf); /// /// 将 buf 中，Length 长的数据写到指定的偏移。有存取权限控制。匿名状态不可用，且在普通用户状态时还需要检查设备的配置。不改变安全状态。 /// /// [in]设备句柄； /// [in]偏移； /// [in]长度，不能超过 60，如果超过则需要写多次； /// [in]等写入的数据缓存区指针； /// <returns>ET_SUCCESS：表示成功。 ET_HARD_ERROR：硬件错误 ET_INVALID_PARAMETER：无效的参数。 ET_NOT_SET_PID：没有设置 PID。 ET_ACCESS_DENY：权限不够。 ET_COMMUNICATIONS_ERROR：没有打开设备。 </returns> [DllImport("FT_ET99_API.dll")] public static extern uint et_Write(IntPtr hHandle, ushort offset, int len, byte[] pucWriteBuf); /// /// 根据参数中指定的种子，产生产品标识。种子长度不能超过 51 个字节。必须在超级用户状态下才能用，调用以后不改变安全状态。 /// /// [in]设备句柄； /// [in]种子； /// [in]种子长度，小于等于 51； /// [out]产生的产品标识, 为固定长度 8 个字节的字符串； /// <returns>ET_SUCCESS：表示成功； ET_HARD_ERROR：硬件错误 ET_INVALID_PARAMETER：无效的参数； ET_ACCESS_DENY：权限不够，需要先验证 SOPIN。 ET_COMMUNICATIONS_ERROR：没有打开设备。 </returns> [DllImport("FT_ET99_API.dll")] public static extern uint et_GenPID(IntPtr hHandle, int seedlen, byte[] pucseed, StringBuilder pid); /// /// 产生 16 字节的随机数，放到参数指定的 BUF中。调用者需要保护 BUF至少16 字节，否则会产生系统的存取异常。该函数在匿名状态不可用，且在函数调用以后，安全状态不变。 /// /// [in]设备句柄 /// [out]等写入的数据缓存区指针 /// <returns></returns> [DllImport("FT_ET99_API.dll")] public static extern uint et_GenRandom(IntPtr hHandle, ref byte[] pucRandBuf); /// /// 产生超级用户 PIN 码 /// /// [in]设备句柄 /// [in]产生超级用户密码需要的种子。 /// [in]种子长度，小于等于 51 /// ：[out]用于存放产生的超级用户密码的缓冲区指针，至少可容纳 16 字节。 /// <returns></returns> [DllImport("FT_ET99_API.dll")] public static extern uint et_GenSOPIN(IntPtr hHandle, int seedlen, byte[] pucseed, StringBuilder pucNewSoPin); /// /// 重新设置普通用户密码为 16 个‘F’，相当于解锁。命令执行成功后，当前安全状态变成超级用户状态。 /// /// [in]设备句柄 /// [in]超级用户密码，16 字节。 /// <returns>如果验证超级PIN码错误，并且错误值在0xF0和ET_PIN_ERR_MAX （0xFF）之间,我们可以通过错误码&ET_PIN_ERR_MASK(0x0F)得到剩余重试次数。如果还回 0xF0 表示已经被锁死，如果还回 0xFF 表示验证出错，且 pin 永远不被锁死</returns> [DllImport("FT_ET99_API.dll")] public static extern uint et_ResetPIN(IntPtr hHandle, byte[] pucSoPin); /// /// 更新参数指定的密钥，此密钥是用于计算 HMAC－MD5 的。其中 KEY的获得，是通过一个纯软件接口 HMAC_MD5（），参见相应说明。匿名状态不可用，且在普通用户状态时还需要检查设备配置。不改变安全状态。 /// /// [in]设备句柄 /// [in]密钥指示，取值范围（1—8） /// [in]KEY缓存区指针, KEY固定为 32 字节。 /// <returns></returns> [DllImport("FT_ET99_API.dll")] public static extern uint et_SetKey(IntPtr hHandle, int Keyid, byte[] pucKeyBuf); /// /// 标准 HMAC_MD5 的软件实现，参照 RFC2104 标准。 /// /// [in]等处理的数据缓存区指针，大于 0 小于等于 51 个字节 /// [in]数据长度，大于 0 小于等于 51 /// [in]密钥，按标准 RFC2104，长度可以任意 /// [in]密钥长度 /// [out]硬件计算需要的 KEY，固定 32 字节。 /// [out]计算结果，固定 16 字节。 /// <returns></returns> [DllImport("FT_ET99_API.dll")] public static extern uint MD5_HMAC(byte[] pucText, byte ulText_Len, byte[] pucKey, byte ulKey_Len, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 32)]byte[] pucToenKey, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 16)]byte[] pucDigest); /// /// 利用硬件计算 HMAC-MD5 ，pid 为出厂时，还回错误。权限等同于 KEY的读权限。不改变安全状态。 /// /// [in]设备句柄 /// [in]密钥指示，范围（1—8） /// [in]待计算的数据，大于 0 小于等于 51 个字节 /// [in]数据长度，大于 0 小于等于 51 /// [out]散列结果的数据指针，固定长度 16 个字节。 /// <returns></returns> [DllImport("FT_ET99_API.dll")] public static extern uint et_HMAC_MD5(IntPtr hHandle, int Keyid, int textLen, byte[] pucText, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 16)]byte[] digest); /// /// 验证密码，以获得相应的安全状态，不受安全状态限制，验证成功以后，进入相应的安全状态。ET_VERIFY_USER_PIN = 验证的是普通用户PIN码，如果验证通过，则进入普通用户状态。 /// /// [in]设备句柄； /// [in]验证 PIN的类型，见下表； /// [in] PIN 码，固定长度 16 个字节。 /// <returns></returns> [DllImport("FT_ET99_API.dll")] public static extern uint et_Verify(IntPtr hHandle, int Flags, byte[] pucPIN); /// /// 修改普通用户密码，从 pucOldPIN，改为 pucNewPIN。普通用户密码长度固定为 16 字节。此命令可以在匿名状态下进行，命令执行成功后，进入普通用户状态。 /// /// [in]设备句柄 /// [in]原来的密码，长度固定为 16 字节 /// [in]新密码，长度固定为 16 字节 /// <returns></returns> [DllImport("FT_ET99_API.dll")] public static extern uint et_ChangeUserPIN(IntPtr hHandle, byte[] pucOldPIN, byte[] pucNewPIN); /// /// 重置安全状态，回到匿名用户状态。 /// /// [in]设备句柄 /// <returns></returns> [DllImport("FT_ET99_API.dll")] public static extern uint et_ResetSecurityState(IntPtr hHandle); /// /// 获得硬件序列号。可以在匿名状态下进行。不改变安全状态。 /// /// [in]设备句柄 /// [out]用于存放获得的序列号，长度固定为 8 字节 /// <returns></returns> [DllImport("FT_ET99_API.dll")] public static extern uint et_GetSN(IntPtr hHandle, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 32)]byte[] pucSN); /// /// 对硬件进行配置。必须在超级用户状态下进行。不改变安全状态。 /// /// [in]设备句柄 /// [in]超级 PIN 码的重试次数，范围 0—15，0 表示永远不被锁死； /// ：[in]用户 PIN 码的重试次数，范围 0—15，0 表示永远不被锁死； /// [in]读写/只读标注，如下表； /// [in]保留字，必须为 0。 /// <returns></returns> [DllImport("FT_ET99_API.dll")] public static extern uint et_SetupToken(IntPtr hHandle, byte bSoPINRetries, byte bUserPINRetries, byte bUserReadOnly, byte bBack); /// /// 打开 LED灯，使其变亮。匿名状态不可用，不改变安全状态。设备加电后，LED灯是常亮的 /// /// [in]设备句柄 /// <returns></returns> [DllImport("FT_ET99_API.dll")] public static extern uint et_TurnOnLED(IntPtr hHandle); /// /// 关闭 LED灯，使其变亮。匿名状态不可用，不改变安全状态。设备加电后，LED灯是常亮的 /// /// [in]设备句柄 /// <returns></returns> [DllImport("FT_ET99_API.dll")] public static extern uint et_TurnOffLED(IntPtr hHandle); internal static void et_Write() { throw new Exception("The method or operation is not implemented."); } } }