範例 C 程式:建立金鑰容器和產生金鑰
下列範例會建立具名 金鑰容器 ,並將 簽章金鑰組 和 交換金鑰組 新增至容器。 即使具名金鑰容器和密碼編譯金鑰已經存在,此範例仍可執行,而不會發生問題。
注意
應用程式不應該使用預設金鑰容器來儲存私密金鑰。 當多個應用程式使用相同的容器時,一個應用程式可能會變更或終結另一個應用程式所需的金鑰。 建議應用程式使用連結至應用程式的金鑰容器。 這樣做可降低其他應用程式竄改應用程式正常運作所需金鑰的風險。
此範例示範下列工作和 CryptoAPI 函式:
- 它會嘗試取得具名金鑰容器。 如果具名金鑰容器不存在,則會建立它。
- 如果金鑰容器中沒有簽章金鑰組,它會在金鑰容器內建立簽章金鑰組。
- 如果金鑰容器中沒有交換金鑰組,它會在金鑰容器內建立交換金鑰組。
這些作業只需要針對每部電腦上的每個使用者執行一次。 如果已建立具名金鑰容器和金鑰組,則此範例不會執行任何作業。
此範例使用下列 CryptoAPI 函式:
此範例會使用 MyHandleError函式。 此函式的程式碼隨附于範例中。 此函式和其他輔助函式的程式碼也會列在常規用途 Functions底下。
//-------------------------------------------------------------------
// Copyright (C) Microsoft. All rights reserved.
#pragma comment(lib, "crypt32.lib")
#include <stdio.h>
#include <tchar.h>
#include <windows.h>
#include <Wincrypt.h>
//-------------------------------------------------------------------
// This example uses the function MyHandleError, a simple error
// handling function to print an error message and exit
// the program.
// For most applications, replace this function with one
// that does more extensive error reporting.
void MyHandleError(LPTSTR psz)
{
_ftprintf(stderr, TEXT("An error occurred in the program. \n"));
_ftprintf(stderr, TEXT("%s\n"), psz);
_ftprintf(stderr, TEXT("Error number %x.\n"), GetLastError());
_ftprintf(stderr, TEXT("Program terminating. \n"));
exit(1);
} // End of MyHandleError.
void main(void)
{
// Handle for the cryptographic provider context.
HCRYPTPROV hCryptProv;
// The name of the container.
LPCTSTR pszContainerName = TEXT("My Sample Key Container");
//---------------------------------------------------------------
// Begin processing. Attempt to acquire a context by using the
// specified key container.
if(CryptAcquireContext(
&hCryptProv,
pszContainerName,
NULL,
PROV_RSA_FULL,
0))
{
_tprintf(
TEXT("A crypto context with the %s key container ")
TEXT("has been acquired.\n"),
pszContainerName);
}
else
{
//-----------------------------------------------------------
// Some sort of error occurred in acquiring the context.
// This is most likely due to the specified container
// not existing. Create a new key container.
if(GetLastError() == NTE_BAD_KEYSET)
{
if(CryptAcquireContext(
&hCryptProv,
pszContainerName,
NULL,
PROV_RSA_FULL,
CRYPT_NEWKEYSET))
{
_tprintf(TEXT("A new key container has been ")
TEXT("created.\n"));
}
else
{
MyHandleError(TEXT("Could not create a new key ")
TEXT("container.\n"));
}
}
else
{
MyHandleError(TEXT("CryptAcquireContext failed.\n"));
}
}
//---------------------------------------------------------------
// A context with a key container is available.
// Attempt to get the handle to the signature key.
// Public/private key handle.
HCRYPTKEY hKey;
if(CryptGetUserKey(
hCryptProv,
AT_SIGNATURE,
&hKey))
{
_tprintf(TEXT("A signature key is available.\n"));
}
else
{
_tprintf(TEXT("No signature key is available.\n"));
if(GetLastError() == NTE_NO_KEY)
{
//-------------------------------------------------------
// The error was that there is a container but no key.
// Create a signature key pair.
_tprintf(TEXT("The signature key does not exist.\n"));
_tprintf(TEXT("Create a signature key pair.\n"));
if(CryptGenKey(
hCryptProv,
AT_SIGNATURE,
0,
&hKey))
{
_tprintf(TEXT("Created a signature key pair.\n"));
}
else
{
MyHandleError(TEXT("Error occurred creating a ")
TEXT("signature key.\n"));
}
}
else
{
MyHandleError(TEXT("An error other than NTE_NO_KEY ")
TEXT("getting a signature key.\n"));
}
} // End if.
_tprintf(TEXT("A signature key pair existed, or one was ")
TEXT("created.\n\n"));
// Destroy the signature key.
if(hKey)
{
if(!(CryptDestroyKey(hKey)))
{
MyHandleError(TEXT("Error during CryptDestroyKey."));
}
hKey = NULL;
}
// Next, check the exchange key.
if(CryptGetUserKey(
hCryptProv,
AT_KEYEXCHANGE,
&hKey))
{
_tprintf(TEXT("An exchange key exists.\n"));
}
else
{
_tprintf(TEXT("No exchange key is available.\n"));
// Check to determine whether an exchange key
// needs to be created.
if(GetLastError() == NTE_NO_KEY)
{
// Create a key exchange key pair.
_tprintf(TEXT("The exchange key does not exist.\n"));
_tprintf(TEXT("Attempting to create an exchange key ")
TEXT("pair.\n"));
if(CryptGenKey(
hCryptProv,
AT_KEYEXCHANGE,
0,
&hKey))
{
_tprintf(TEXT("Exchange key pair created.\n"));
}
else
{
MyHandleError(TEXT("Error occurred attempting to ")
TEXT("create an exchange key.\n"));
}
}
else
{
MyHandleError(TEXT("An error other than NTE_NO_KEY ")
TEXT("occurred.\n"));
}
}
// Destroy the exchange key.
if(hKey)
{
if(!(CryptDestroyKey(hKey)))
{
MyHandleError(TEXT("Error during CryptDestroyKey."));
}
hKey = NULL;
}
// Release the CSP.
if(hCryptProv)
{
if(!(CryptReleaseContext(hCryptProv, 0)))
{
MyHandleError(TEXT("Error during CryptReleaseContext."));
}
}
_tprintf(TEXT("Everything is okay. A signature key "));
_tprintf(TEXT("pair and an exchange key exist in "));
_tprintf(TEXT("the %s key container.\n"), pszContainerName);
} // End main.