在调用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 */两行注释掉,存盘,即可编译成功。