範例 C 程式:從密碼衍生工作階段金鑰
下列範例示範如何從密碼雜湊建立會話密碼編譯金鑰,以及使用CryptDeriveKey函式和相關函式。
此範例說明下列工作和 CryptoAPI 函式:
- 呼叫 CryptAcquireCoNtext 以取得預設 CSP 和預設 金鑰容器的控制碼。
- 使用 CryptCreateHash 建立空的雜湊物件。
- 使用 CryptHashData雜湊密碼的文字。
- 使用 CryptDeriveKey從雜湊密碼衍生工作階段金鑰。
- 終結雜湊和密碼。
- 使用 CryptReleaseCoNtext 釋放 CSP。
此範例會使用 MyHandleError函式。 此函式的程式碼隨附于範例中。
此函式和其他輔助函式的程式碼也會列在常規用途 Functions底下。
#pragma comment(lib, "crypt32.lib")
#include <stdio.h>
#include <string.h>
#include <conio.h>
#include <windows.h>
#include <Wincrypt.h>
#define MY_ENCODING_TYPE (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)
void MyHandleError(char *s);
void GetConsoleInput(char*, UINT);
#define PASSWORD_LENGTH 512
void main()
{
//----------------------------------------------------------------
// Copyright (C) Microsoft. All rights reserved.
// Declare and initialize variables.
HCRYPTPROV hCryptProv;
HCRYPTKEY hKey;
HCRYPTHASH hHash;
CHAR szPassword[PASSWORD_LENGTH] = "";
DWORD dwLength;
//----------------------------------------------------------------
// Get the password from the user.
fprintf(stderr,"Enter a password to be used to create a key:");
// Get a password while printing only asterisks to the screen.
GetConsoleInput(szPassword, PASSWORD_LENGTH);
printf("The password has been stored.\n");
dwLength = (DWORD) strlen(szPassword);
//----------------------------------------------------------------
// Acquire a cryptographic provider context handle.
if(CryptAcquireContext(
&hCryptProv,
NULL,
NULL,
PROV_RSA_FULL,
0))
{
printf("A context has been acquired. \n");
}
else
{
MyHandleError("Error during CryptAcquireContext!");
}
//----------------------------------------------------------------
// Create an empty hash object.
if(CryptCreateHash(
hCryptProv,
CALG_MD5,
0,
0,
&hHash))
{
printf("An empty hash object has been created. \n");
}
else
{
MyHandleError("Error during CryptCreateHash!");
}
//----------------------------------------------------------------
// Hash the password string.
if(CryptHashData(
hHash,
(BYTE *)szPassword,
dwLength,
0))
{
printf("The password has been hashed. \n");
}
else
{
MyHandleError("Error during CryptHashData!");
}
//----------------------------------------------------------------
// Create a session key based on the hash of the password.
if(CryptDeriveKey(
hCryptProv,
CALG_RC2,
hHash,
CRYPT_EXPORTABLE,
&hKey))
{
printf("The key has been derived. \n");
}
else
{
MyHandleError("Error during CryptDeriveKey!");
}
//----------------------------------------------------------------
// Use hKey as appropriate to encrypt or decrypt a message.
//----------------------------------------------------------------
// Clean up.
// Destroy the hash object.
if(hHash)
{
if(!(CryptDestroyHash(hHash)))
MyHandleError("Error during CryptDestroyHash");
}
// Destroy the session key.
if(hKey)
{
if(!(CryptDestroyKey(hKey)))
MyHandleError("Error during CryptDestroyKey");
}
// Release the provider handle.
if(hCryptProv)
{
if(!(CryptReleaseContext(hCryptProv, 0)))
MyHandleError("Error during CryptReleaseContext");
}
printf("The program to derive a key completed without error. \n");
} // end main
//--------------------------------------------------------------------
// 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(char *s)
{
printf("An error occurred in running the program.\n");
printf("%s\n",s);
printf("Error number %x\n.",GetLastError());
printf("Program terminating.\n");
exit(1);
}
//--------------------------------------------------------------------
// The GetConsoleInput function gets an array of characters from the
// keyboard, while printing only asterisks to the screen.
void GetConsoleInput(char* strInput,
UINT intMaxChars)
{
char ch;
char minChar = ' ';
minChar++;
ch = (char)_getch();
while (ch != '\r')
{
if (ch == '\b' && strlen(strInput) > 0)
{
strInput[strlen(strInput)-1] = '\0';
printf("\b \b");
}
else if ((ch >= minChar) && (strlen(strInput) < intMaxChars))
{
strInput[strlen(strInput)+1] = '\0';
strInput[strlen(strInput)] = ch;
_putch('*');
}
ch = (char)_getch();
}
_putch('\n');
}