现在的位置: 首页 > 综合 > 正文

如何: 用加密API获得纯文本的会话密钥

2018年06月10日 ⁄ 综合 ⁄ 共 2524字 ⁄ 字号 评论关闭
运行环境: 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. 加入库连接:

{0> crypt32.lib <}0{>? crypt32.lib

例子代码如下:?<0}

#include <windows.h>
#include <wincrypt.h>
#include <stdio.h>

#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);
    }
 
  }

} // 结束

抱歉!评论已关闭.