对“用CryptoAPI进行数据加密”一文的补充

发表于:2007-07-04来源:作者:点击数: 标签:
武汉 程义军 读了贵刊2000年第19期B16版“用CryptoAPI进行数据加密”一文,觉得很有所获,急忙将其键入,编译、运行,却出现了错误。当然,并不是原文提供的代码有错,而是原文的作者忽略了一个重要的问题。如果你的机器曾运行过这种数据加密程序,那当然可以
武汉 程义军

  读了贵刊2000年第19期B16版“用CryptoAPI进行数据加密”一文,觉得很有所获,急忙将其键入,编译、运行,却出现了错误。当然,并不是原文提供的代码有错,而是原文的作者忽略了一个重要的问题。如果你的机器曾运行过这种数据加密程序,那当然可以正确地运行。如果是第一次才运行此程序,那将会出现问题,错误就在 CryptAcquireContext的调用上。

  在调用CryptEncrypt进行数据加密之前,需要取得当前机器缺省的密钥容器,而CryptAcquireContext(&hProv,NULL,NULL,PROV_RSA_FULL,0)就是用于连接缺省的CSP的,如果当前机器未曾设置过缺省的密钥容器, CryptAcquireContext 调用就会出错。因此必须为机器创建缺省的密钥容器。

  创建缺省的密钥容器也需要调用CryptoAPI进行。下面介绍一种创建缺省的密钥容器的控制台程序InitUser.c。本程序的功能为: 用你的机器名称UserName创建一个缺省的密钥容器。 在密钥容器中创建一个数字签名密钥对。 在密钥容器中创建一个密钥交换对。

  本程序在一台机器上只须执行一次,执行之后,你将会看到在系统注册表的HKEY_CURRENT_USER\Software\microsoft下多了一个主键: Cryptography\UserKeys,并填入一些十六进制的值。之后,你就可以顺利地使用数据加密程序了,甚至可以使用数字签名了。

  程序清单: < InitUser.c > #include < windows.h > #include < stdio.h > #include < stdlib.h > #include < wincrypt.h > //主程序不需要任何参数 void _cdecl main(void) { HCRYPTPROV hProv; HCRYPTKEY hKey; CHAR szUserName[100]; DWORD dwUserNameLen = 100; // 试图获取缺省的密钥容器, 若失败,则创建一个缺省容器 if(!CryptAcquireContext(&hProv, NULL, MS_DEF_PROV, PROV_RSA_FULL, 0)) { //若获取缺省密钥容器发生错误, 就创建一个缺省密钥容器, 使用参数 CRYPT_NEWKEYSET if(!CryptAcquireContext (&hProv,NULL,MS_DEF_PROV, PROV_RSA_FULL,CRYPT_NEWKEYSET)) { printf(“创建缺省密钥容器发生错误!\n"); exit(1); } // 取得缺省密钥容器名 if(!CryptGetProvParam(hProv, PP_CONTAINER, szUserName, &dwUserNameLen, 0)) { // 出错误时容器名置空 szUserName[0] = 0; } printf(“Create key container ‘%s'\n",szUserName); } // 试图获取签名密钥的名柄 if(!CryptGetUserKey(hProv, AT_SIGNATURE, &hKey)) { if(GetLastError() == NTE_NO_KEY) { // 创建数字签名密钥对 printf(“Create signature key pair\n"); if(!CryptGenKey(hProv,AT_SIGNATURE,0,&hKey)) { printf(“错误代码: %x 创建数字签名 密钥对发生错误!\n", GetLastError()); exit(1); } else { CryptDestroyKey(hKey); } } else { printf(“错误代码: %x during CryptGetUserKey!\n", GetLastError()); exit(1); } } // 试图取得交换密钥的句柄, 没有交换密钥时,创建交换密钥 if(!CryptGetUserKey(hProv,AT_KEYEXCHANGE,&hKey)) { if(GetLastError()==NTE_NO_KEY) {//没有交换密钥时,创建交换密钥对 printf(“创建交换密钥\n"); if(!CryptGenKey(hProv,AT_KEYEXCHANGE,0,&hKey)) { printf(“Error %x during CryptGenKey!\n", GetLastError()); exit(1); } else { CryptDestroyKey(hKey); } } else { printf(“Error %x duringCryptGetUserKey!\n", GetLastError()); exit(1); } } CryptReleaseContext(hProv,0); //释放句柄 printf(“OK\n"); exit(0); }

  以上程序在WinNT4.0及Win98、VC5++上编译通过,机器环境为赛扬333。若编译时发生HCRYPTPROV、HCRYPTKEY类型等错误,请打开 vc\include\wincrypt.h,将其头部的#if(_WIN32_WINNT >= 0x0400)及尾部的#endif /* _WIN32_WINNT >= 0x0400 */两行注释掉,存盘,即可编译成功。    

原文转自:http://www.ltesting.net