예제 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');
}