您的位置:首页 > 运维架构

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

2010-05-26 23:00 441 查看
通过前面的文章,我们已经掌握了如下5项技术:

通过WDK获取设备的VID-PID、网卡原生MAC地址、硬盘序列号

通过WMI获取网卡MAC地址、硬盘序列号、主板序列号、CPU ID、BIOS序列号

MD5加密及HMAC-MD5加密(VC源代码)

BASE64编码和解码(VC源代码)

基于内存映射文件方式读写ini文件

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

读取配置文件,依次获取需要查询的设备类别。每种设备类别对应ini文件中的一个[Section]。

根据设备类别,从配置文件的[Section]中获取查询模式(WDK查询或WMI查询)以及查询编号,然后执行指定查询,获取所有该类设备的特征值。

将特征值作为Key,判断其是否出现在当前[Section]中。如果出现,则获取其Value。Value中的每一个bit位代表一个软件或者一个功能点。

对Key=Value做HMAC_MD5校验,防止数据被篡改。

将获得的所有有效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:splashcn@msn.com

版本历史:
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息