方案集成-采用配置文件实现多个软件对多个硬件的加密

通过前面的文章,我们已经掌握了如下5项技术:

  1. 通过WDK获取设备的VID-PID、网卡原生MAC地址、硬盘序列号
  2. 通过WMI获取网卡MAC地址、硬盘序列号、主板序列号、CPU ID、BIOS序列号
  3. MD5加密及HMAC-MD5加密(VC源代码)
  4. BASE64编码和解码(VC源代码)
  5. 基于内存映射文件方式读写ini文件

现在我将综合这5项技术,通过配置文件实现多个软件对多个硬件的加密。其实现思路如下:

  1. 读取配置文件,依次获取需要查询的设备类别。每种设备类别对应ini文件中的一个[Section]。
  2. 根据设备类别,从配置文件的[Section]中获取查询模式(WDK查询或WMI查询)以及查询编号,然后执行指定查询,获取所有该类设备的特征值。
  3. 将特征值作为Key,判断其是否出现在当前[Section]中。如果出现,则获取其Value。Value中的每一个bit位代表一个软件或者一个功能点。
  4. 对Key=Value做HMAC_MD5校验,防止数据被篡改。
  5. 将获得的所有有效Value相加,得到总的授权软件或者功能点信息。

开发语言:Visual C++

支持平台:Windows

实现功能:采用配置文件实现多个软件对多个硬件的加密

下载地址:

DeviceQuery.zip

版本历史:

V1.5 2010年05月24日  

  • 改进配置文件设计。 

V1.4 2010年05月11日  

  • 密文采用BASE64编码输出。   

V1.3 2010年04月30日  

  • 修正微软MSDN例子错误,并增加对虚拟网卡的判断。

V1.2 2010年04月27日

  • 加入WMI查询。 

V1.1 2010年04月21日

  • 改进配置文件设计。

V1.0 2010年04月15日

  • 完成正式版本,具备WDK查询。

接口函数:

INI_DeviceQuery

配置文件格式:

;人机交互设备(VID-PID=dwKey|HMAC) [HID] MODE=WDK TYPE=0 046D-C315=0x00000012|Mo3hF5lC8sAWhKHdwvT16g== 046D-C52B=0x00000012|ViJPd8F8tawxfnzT6R2TLQ== ;网卡原生MAC地址 [NIC-PA] MODE=WDK TYPE=1 6CF049007689=0x00000020|9Vw9VDxuQIQIP/A+171AZw== 002719AA763A=0x00000020|p84cf1r55foKEm2qzkmEaw== ;硬盘序列号 [HARDDISK] MODE=WMI TYPE=1 V90XHAT2=0x00000040|WrZMdQZbBXFKM8m0JRxPkg== N9CBZ0TY=0x00000040|ayyn1kGrK9GhAX1/8NH3Iw== ;主板序列号 ;[BASEBOARD-SN] ;MODE=WMI ;TYPE=2 ;CPU ID ;[CPU] ;MODE=WMI ;TYPE=3 ;BIOS序列号 ;[BIOS] ;MODE=WMI ;TYPE=4 ;主板型号 [BASEBOARD-MODEL] MODE=WMI TYPE=5 P55A-UD3R=0x0000000F|f3dVTbLWaiCyM+iWfP1vnA==

源代码:

INI_DeviceQuery.h

/* ---------------------------------------------------------- 文件名称:INI_DeviceQuery.h 作者:秦建辉 MSN:[email protected] 版本历史: V1.5 2010年05月24日 改进配置文件设计。 V1.4 2010年05月11日 密文采用BASE64编码输出。 V1.3 2010年04月30日 修正微软MSDN例子错误,并增加对虚拟网卡的判断。 V1.2 2010年04月27日 加入WMI查询。 V1.1 2010年04月21日 改进配置文件设计。 V1.0 2010年04月15日 完成正式版本,具备WDK查询。 功能描述: 采用配置文件实现对各种硬件加密 接口函数: INI_DeviceQuery ------------------------------------------------------------ */ #pragma once #include <windows.h> // 回调函数,用于校验明文密文是否匹配 typedef BOOL (CALLBACK* FP_HMAC_Verify)( const TCHAR* szPlainText, const TCHAR* szCipherText ); // 回调函数,用于打印 typedef void (CALLBACK* FP_Show_DeviceKey)( const TCHAR* szDeviceKey ); #ifdef __cplusplus extern "C" { #endif /* 功能:获取授权产品列表 参数说明: iniFileName:授权产品配置文件名 fp_Verify:回调函数,用于数据校验,防止信息篡改。如果为NULL,则使用内部的校验函数。 fp_Show:回调函数,调试分析时用于获取更具体信息。正式使用时设为NULL。 返回值: 授权产品总列表 */ DWORD INI_DeviceQuery( const TCHAR* iniFileName, FP_HMAC_Verify fp_Verify = NULL, FP_Show_DeviceKey fp_Show = NULL ); #ifdef __cplusplus } #endif

INI_DeviceQuery.cpp

#include "INI_DeviceQuery.h" #include "..//WDK_DeviceQuery//WDK_DeviceQuery.h" #include "..//WMI_DeviceQuery//WMI_DeviceQuery.h" #include "..//HMACMD5//HMAC_MD5_API.h" #include "..//RWINIFILE//RWINIFILE.h" #include <tchar.h> #include <strsafe.h> // 判断明文密文是否匹配 static BOOL __stdcall HMACMD5_Verify( const TCHAR* szPlainText, const TCHAR* szCipherText ) { const TCHAR* secretKey = TEXT("大梦谁先觉?平生我自知。草堂春睡足,窗外日迟迟。"); // 加密密钥 TCHAR hmacCipher[32]; INT iLen; // 计算明文的哈希值 iLen = HMAC_MD5_BASE64( reinterpret_cast<const BYTE*>(szPlainText), _tcslen( szPlainText ) * sizeof(TCHAR), reinterpret_cast<const BYTE*>(secretKey), _tcslen(secretKey) * sizeof(TCHAR), hmacCipher ); // 将密文文本和校验码进行比对 if( _tcsncmp( hmacCipher, szCipherText, iLen ) == 0 ) { return TRUE; } else { return FALSE; } } DWORD INI_DeviceQuery( const TCHAR* iniFileName, FP_HMAC_Verify fp_Verify, FP_Show_DeviceKey fp_Show ) { TCHAR szSectionNames[1024]; // 存储所有的分区名 TCHAR szKeyValue[64]; // 存储键值及校验字符串“KEY|HMAC” TCHAR szPlainText[80]; // 存储去掉校验字符串后的“VID-PID=KEY” TCHAR *pDest; UINT uIndex; DWORD dwSubKey, dwAllKey = 0; CRWINIFILE iniFile; // 如果校验函数为空,则使用缺省校验函数 if( fp_Verify == NULL ) { fp_Verify = HMACMD5_Verify; } // 读取授权产品配置文件 if( !iniFile.LoadFile( iniFileName, GENERIC_READ, 0, TRUE ) ) { return 0; } // 获取产品分类 if( iniFile.GetProfileSectionNames( szSectionNames, sizeof(szSectionNames)/sizeof(TCHAR) ) > 0 ) { for( uIndex = 0; szSectionNames[uIndex] != 0; uIndex += _tcslen( szSectionNames + uIndex ) + 1 ) { TCHAR szMode[16]; INT iQueryType; // 获取查询类型 iQueryType = iniFile.GetProfileInt( szSectionNames + uIndex, TEXT("TYPE"), -1 ); // 获取查询方式(WDK查询还是WMI查询) if( iniFile.GetProfileString( szSectionNames + uIndex, TEXT("MODE"), NULL, szMode, sizeof(szMode)/sizeof(TCHAR) ) > 0 ) { T_DEVICE_PROPERTY properties[32]; INT iDevNum = 0; if( _tcsicmp( szMode, TEXT("WDK") ) == 0 ) { iDevNum = WDK_DeviceQuery_Property( iQueryType, properties, sizeof(properties)/sizeof(T_DEVICE_PROPERTY) ); } else if( _tcsicmp( szMode, TEXT("WMI") ) == 0 ) { iDevNum = WMI_DeviceQuery( iQueryType, properties, sizeof(properties)/sizeof(T_DEVICE_PROPERTY) ); } for( INT i = 0; i < iDevNum; i++ ) { if( iniFile.GetProfileString( szSectionNames + uIndex, properties[i].szProperty, NULL, szKeyValue, sizeof(szKeyValue)/sizeof(TCHAR) ) > 0 ) { // 查找分隔符 pDest = _tcschr( szKeyValue, TEXT('|') ); if( pDest != NULL ) { // 析取授权产品列表 *pDest++ = TEXT('/0'); StringCchPrintf( szPlainText, sizeof(szPlainText)/sizeof(TCHAR), TEXT("%s=%s"), properties[i].szProperty, szKeyValue ); // 回调函数,对数据一致性做校验 if( fp_Verify( szPlainText, pDest ) ) { dwSubKey = _tcstoul( szKeyValue, NULL, 0 ); dwAllKey |= dwSubKey; // 回调函数获取具体信息 if( fp_Show != NULL ) { fp_Show( szPlainText ); } } } } } // End for i } } // End for uIndex } iniFile.CloseFile(); return dwAllKey; }

你可能感兴趣的:(加密,properties,null,ini,FP,2010)