例 C プログラム: パスワードからセッション キーを派生させる
次の例では、パスワードのハッシュからセッション暗号化キーを作成し、関数 CryptDeriveKey と関連関数を使用する方法を示します。
この例では、次のタスクと CryptoAPI 関数を示します。
- CryptAcquireContext を呼び出して、既定の CSP と既定のキー コンテナーのハンドルを取得します。
- CryptCreateHash を使用して空のハッシュ オブジェクトを作成する。
- CryptHashData を使用してパスワードのテキストをハッシュする。
- CryptDeriveKey を使用してハッシュされたパスワードからセッション キーを派生させる。
- ハッシュとパスワードの破棄。
- CryptReleaseContext を使用して CSP をリリースする。
この例では、 関数 MyHandleError を使用します。 この関数のコードは、サンプルに含まれています。
この関数およびその他の補助関数のコードは、General Purpose関数にも一覧表示されます。
#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');
}