运行环境: VC6 SP5, 2000 SP1,NT4 SP3。
在通常的编程中获得会话密钥匙非常重要的。 然而,微软的加密操作API(无论是基础的还是增强的)都不能提供这项功能。 CryptExportKey() 和 CryptImportKey() 各自要求一个有效的密钥句柄来对会话密钥进行加密和解密。 MSDN 展示了一种使用私钥的方法。 但是微软的这个在MSDN中例子相当的长。 下面的这个方法不仅更快而且更有效。
在运行这个例子前,需要在Project -> Settings (Visual Studio 6.0 ) 中对以下参数进行设置:
1.添加C++预处理定义:_WIN32_WINNT=0x0500, _CRYPT32_(WIN2K)或者 _WIN32_WINNT=0x0400, _CRYPT32_(NT4)
2. 加入库连接:crypt32.lib
例子代码如下:
#include #include #include #define KEY_PAIR_SIZE dwSize - 12 #define SESSION_KEY_SIZE dwKeyMaterial void main() { HCRYPTPROV hProv = 0; HCRYPTKEY hExchangeKeyPair = 0; HCRYPTKEY hSessionKey = 0; BYTE *pbKeyMaterial = NULL; DWORD dwKeyMaterial ; BYTE *pbExportedKeyBlob = NULL; BYTE *pbEncryptedKey = NULL; DWORD dwSize; unsigned int c; __try { if (!CryptAcquireContext( &hProv, "Container Name", MS_ENHANCED_PROV , PROV_RSA_FULL, CRYPT_MACHINE_KEYSET )) { __leave; } //--------------------------------------------------- //创建一个会话密钥。 在这个例子中我们将使用一个168位的3DES key。 if (!CryptGenKey( hProv, CALG_3DES, CRYPT_EXPORTABLE, &hSessionKey )) { __leave; } //--------------------------------------------------- //得到交换密钥对的句柄 if (!CryptGetUserKey( hProv, AT_KEYEXCHANGE, &hExchangeKeyPair)) { __leave; } //-------------------------------------------------------- //用密钥对中公钥部分对会话密钥进行加密 //第一次先获得已加密的会话密钥的必要字节大小 //然后将其输出。 if (!CryptExportKey( hSessionKey, hExchangeKeyPair, SIMPLEBLOB, 0, NULL, &dwSize)) { __leave; } pbExportedKeyBlob = new BYTE[dwSize]; if (!CryptExportKey( hSessionKey, hExchangeKeyPair, SIMPLEBLOB, 0, pbExportedKeyBlob, &dwSize)) { __leave; } //-------------------------------------------------------- //我们删除第一个12字节大小的Blob 信息 pbEncryptedKey = new BYTE [KEY_PAIR_SIZE]; for ( c = 0 ; c < KEY_PAIR_SIZE ; c++ ) { pbEncryptedKey[c] = pbExportedKeyBlob[c+12]; } //-------------------------------------------------------- //此时我们用密钥对中的私钥部分就可以得到会话密钥的值。 if (!CryptDecrypt( hExchangeKeyPair, 0, TRUE, 0, pbEncryptedKey, &dwKeyMaterial)) { __leave; } //------------------------------------------------------- // pbKeyMaterial中存放着密钥的值 pbKeyMaterial = new BYTE[ SESSION_KEY_SIZE ]; for ( c = 0; c < SESSION_KEY_SIZE ; c++ ) { pbKeyMaterial[c] = pbEncryptedKey[c]; } } __finally { if (pbKeyMaterial ) LocalFree(pbKeyMaterial ); if (hSessionKey) CryptDestroyKey(hSessionKey); if (hExchangeKeyPair) CryptDestroyKey(hExchangeKeyPair); if (hProv) { CryptReleaseContext(hProv, 0); } } } // 结束
|