Exemple de programme C : dérivation d’une clé de session à partir d’un mot de passe
L’exemple suivant illustre la création d’une clé de chiffrement de session à partir du hachage d’un mot de passe, ainsi que l’utilisation de la fonction CryptDeriveKey et des fonctions associées.
Cet exemple illustre les tâches et fonctions CryptoAPI suivantes :
- Appel de CryptAcquireContext à l’acquisition d’un handle pour le fournisseur de solutions Cloud par défaut et le conteneur de clés par défaut.
- Utilisation de CryptCreateHash pour créer un objet de hachage vide.
- Hachage du texte d’un mot de passe à l’aide de CryptHashData.
- Dérivation d’une clé de session à partir du mot de passe haché à l’aide de CryptDeriveKey.
- Destruction du hachage et du mot de passe.
- Utilisation de CryptReleaseContext pour libérer le csp.
Cet exemple utilise la fonction MyHandleError. Le code de cette fonction est inclus dans l’exemple.
Le code de cette fonction auxiliaire et d’autres fonctions auxiliaires est également répertorié sous usage général Fonctions.
#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');
}