在使用CyptoAPI对口令进行加密编程前,必须预先建立密钥容器和密钥。若未对此进行预处理,由于在后续编程中需要在调用CyptEncrpt()进行数据加密之前首先获取到当前机器缺省的密钥容器。这十用于连接默认CSP并获取默认密钥容器的函数CryptAcquireContext()的调用就会出错。因此必须在进行加密运算之前确保机器已经建立了默认的密钥容器。下面的Initia()函数将在程序初始化时被调用用以建立密钥容器和密钥:
Void CWorkTimeApp::Initial()
{
HCRYPTPROV hProv;
HCRYPTKEY hKey;
Unsigned char szUserName[100];
DWORD dwUserNameLen=100;
//试图获取默认密钥容器句柄
If(!CrypAcquireContext(&hProv,NULL,MS_DEF_PROV,PROV_RSA_FULL,0))
{
//创建默认密钥容器
If(!CryptAcquireContext(&hProv,NULL,MS_DEF_PROV,PROV_RSA_FULL,CRYPT_NEWKEYSET))
PostQuitMessage(1);
//获取默认密钥容器名
If(!CryptGetProvParam(hProv,PP_CONTAINER,szUserName,&dwUserNameLen,0))
szUsername[0]=0;
}
//视图得到签名密钥句柄
If(!CryptGetUserKey(hProv,AT_SIGNATURE,&hKey))
{
If(GetLastError()==NTE_NO_KEY)
{
//创建签名密钥对
If(!CryptGenKey(hProv,AT_SIGNATURE,0,&hKey))
PostQuitMessage(1);
Else
CryptDestroyKey(hKey);
}
Else
PostQuitMessage(1);
}
//试图获取交换密钥句柄
If(!CryptGetUserKey(hProv,AT_KEYEXCHANGE,&hKey))
{
If(GetLastError()==NTE_NO_KEY)
{
//创建交换密钥对
If(!CryptGenKey(hProv,AT_KEYEXCHANGE,0,&hKey))
PostQuitMessage();
Else
CryptDestroyKey(hKey);
}
Else
PostQuitMessage(1);
}
CryptReleaseContext(hProv,0);
}
上述代码通过机器名UserName创建了一个默认的密钥容器并在其中创建了一个数字签名密钥对和一个交换密钥对。在注册表的HKEY_LOCAL_USER/Software/Microsoft下增添一个主键:Cryptgraphy/UserKeys,内有EPbK、ExchTypeSubType、PSKEYS、RandSeed、SigTypeSubType以及SPbK等几个十六进制键值。