Un petit exemple démontrant l'utilisation des fonctions cryptographiques intégrés à Windows, en utilisant les API fournies par Microsoft.
L'exemple génère une clef AES 128 bits, la stocke dans un fichier, chiffre ensuite un autre fichier avec cette clef, puis effectue l'opération inverse.
L'avantage de cette méthode comparée à une implémentation brute de l'algorithme AES est que les fonctions cryptographiques fournies par microsoft sont certifiées FIPS 140-1 niveau 1.
Attention, l'AES ne fonctionne pas à priori sous Windows 2000 et NT, pas de problèmes avec XP ou 2003.
Le zip contient en plus le projet Visual Studio.
Source / Exemple :
#include <Windows.h>
#include <Wincrypt.h>
#include <stdio.h>
#include <math.h>
// Configuration de la démo.
#define NOM_FICHIER_CLEF "maClefAES.txt"
#define NOM_FICHIER_DATA_CLAIR "monFichierClair.txt"
#define NOM_FICHIER_DATA_CHIFFRE "monFichierChiffre.aes"
#define NOM_FICHIER_DATA_DECHIFFRE "monFichierDechiffre.txt"
// Déclaration des variables globales
HCRYPTPROV cryptographicServiceProvider = 0;
HCRYPTKEY clef = 0;
void Erreur(char* fonction)
{
fprintf(stderr, "Erreur %s 0x%x\n", fonction, GetLastError());
}
void Message(char* message)
{
fprintf(stdout, "%s", message);
}
void Initialiser()
{
// Initialisation
Message("\n[Initialisation]\n");
Message("CryptAcquireContext...\n");
if(!CryptAcquireContext(&cryptographicServiceProvider,
NULL,
NULL,
PROV_RSA_AES,
CRYPT_VERIFYCONTEXT))
Erreur("CryptAcquireContext");
}
void Nettoyer()
{
// Nettoyage
Message("\n[Nettoyage]\n");
if (clef)
{
Message("CryptDestroyKey...\n");
CryptDestroyKey(clef);
clef = 0;
}
if (cryptographicServiceProvider)
{
Message("CryptReleaseContext...\n");
CryptReleaseContext(cryptographicServiceProvider, 0);
cryptographicServiceProvider = 0;
}
}
void GenererClef()
{
DWORD modeChiffrement = CRYPT_MODE_CBC;
Message("\n[Generation de la clef]\n");
Message("CryptGenKey...\n");
if(!CryptGenKey(cryptographicServiceProvider,
CALG_AES_128,
CRYPT_EXPORTABLE,
&clef))
Erreur("CryptGenKey");
CryptSetKeyParam(clef, KP_MODE,(BYTE*)&modeChiffrement, NULL);
}
void ExporterClef(char* nomFichier)
{
// Déclaration des variables locales
DWORD longueurClefFormatTexte = 0;
LPBYTE clefFormatTexte = 0;
HANDLE fichier = 0;
DWORD nombreOctetsEcrits = 0;
// Premiere partie du Traitement
Message("\n[Formatage de la clef]\n");
// Obtenir la taille de la clef
Message("CryptExportKey...\n");
if (!CryptExportKey(clef, NULL, PLAINTEXTKEYBLOB, 0, NULL, &longueurClefFormatTexte))
Erreur("CryptExportKey");
// Creer une zone tampon de la taille récupérée
Message("malloc...\n");
if (!(clefFormatTexte = (BYTE *)malloc(longueurClefFormatTexte)))
Erreur("malloc");
// Récupérer la clef
Message("CryptExportKey...\n");
if (!CryptExportKey(clef, NULL, PLAINTEXTKEYBLOB, 0, clefFormatTexte, &longueurClefFormatTexte))
Erreur("CryptExportKey");
// Seconde partie du traitement
Message("\n[Exportation de la clef]\n");
// Créér le fichier qui va stocker la clef
Message("CreateFile...\n");
if ((fichier = CreateFile(nomFichier,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL)) == INVALID_HANDLE_VALUE)
Erreur("CreateFile");
// Ecrire la clef dans le fichier
Message("WriteFile...\n");
if (!WriteFile(fichier, (LPCVOID)clefFormatTexte, longueurClefFormatTexte, &nombreOctetsEcrits, NULL))
Erreur("WriteFile");
// Derniere partie du traitement.
Message("\n[Exportation de la clef terminee]\n");
// Fermer le fichier
if (fichier)
{
Message("CloseHandle...\n");
CloseHandle(fichier);
}
// Libérer le tampon stockant la clef sous forme de texte
if (clefFormatTexte)
{
Message("free...\n");
free(clefFormatTexte);
}
}
void ImporterClef(char* nomFichier)
{
// Déclaration des variables locales
DWORD longueurClefFormatTexte = 0;
LPBYTE clefFormatTexte = 0;
HANDLE fichier = 0;
// Premiere partie du Traitement
Message("\n[Formatage de la clef]\n");
// Ouvrir le fichier contenant la clef
Message("CreateFile...\n");
if ((fichier = CreateFile(nomFichier, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL)) == INVALID_HANDLE_VALUE)
Erreur("CreateFile");
// Obtenir la taille du fichier
Message("GetFileSize...\n");
if ((longueurClefFormatTexte = GetFileSize(fichier, NULL)) == INVALID_FILE_SIZE)
Erreur("GetFileSize");
// Creer une zone tampon pour stocker la clef
Message("malloc...\n");
if (!(clefFormatTexte = (BYTE *)malloc(longueurClefFormatTexte)))
Erreur("malloc");
// Lire la clef à partir du fichier
Message("ReadFile...\n");
if (!ReadFile(fichier, clefFormatTexte, longueurClefFormatTexte, &longueurClefFormatTexte, NULL))
Erreur("ReadFile");
// Seconde partie du Traitement
Message("\n[Importation de la clef]\n");
// Importer la clef dans le CSP
Message("CryptImportKey...\n");
if (!CryptImportKey(cryptographicServiceProvider, clefFormatTexte, longueurClefFormatTexte, 0, 0, &clef))
Erreur("CryptImportKey");
// Derniere partie du traitement.
Message("\n[Importation de la clef terminee]\n");
// Fermer le fichier
if (fichier)
{
Message("CloseHandle...\n");
CloseHandle(fichier);
}
// Libérer le tampon stockant la clef sous forme de texte
if (clefFormatTexte)
{
Message("free...\n");
free(clefFormatTexte);
}
}
void Chiffrer(char* nomFichierClair, char* nomFichierChiffre)
{
// Déclaration des variables locales
HANDLE fichierClair = 0;
HANDLE fichierChiffre = 0;
LPBYTE texteClair = 0;
LPBYTE texteChiffre = 0;
DWORD longueurTexteClair = 0;
DWORD longueurBlocTexte = 0;
DWORD longueurTexteChiffre = 0;
DWORD nombreOctetsEcrits = 0;
// Ouvrir le fichier clair
Message("CreateFile...\n");
if ((fichierClair = CreateFile(nomFichierClair, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL)) == INVALID_HANDLE_VALUE)
Erreur("CreateFile");
//Obtenir la taille du fichier
Message("GetFileSize...\n");
if ((longueurTexteClair = GetFileSize(fichierClair, NULL)) == INVALID_FILE_SIZE)
Erreur("GetFileSize");
// Creer une zone tampon pour stocker le texte clair
Message("malloc...\n");
if (!(texteClair = (BYTE *)malloc(longueurTexteClair)))
Erreur("malloc");
// Lire le texte à partir du fichier
Message("ReadFile...\n");
if (!ReadFile(fichierClair, texteClair, longueurTexteClair, &longueurTexteClair, NULL))
Erreur("ReadFile");
// Obtenir la taille d'un bloc de texte chiffré
Message("CryptEncrypt...\n");
if (!CryptEncrypt(clef, NULL, TRUE, 0, NULL, &longueurBlocTexte, 0))
Erreur("CryptEncrypt");
// Déterminer la taille du tampon de sortie selon la règle suivante:
// If the key is a block cipher key, the data is padded to a multiple of the
// block size of the cipher. If the data length equals the block size of the
// cipher, one additional block of padding is appended to the data.
double longueurTemp = (static_cast <double> (longueurTexteClair)) / (static_cast <double> (longueurBlocTexte));
longueurTexteChiffre = longueurBlocTexte + (longueurBlocTexte * (static_cast <unsigned int> (floor(longueurTemp))));
// Allouer l'espace mémoire pour le tampon de sortie
Message("malloc...\n");
if (!(texteChiffre = (BYTE *) malloc(longueurTexteChiffre)))
Erreur("malloc");
// Initialiser tampon de sortie
DWORD longueurDonnees = longueurTexteClair;
memset(texteChiffre, ' ', longueurTexteChiffre);
memcpy(texteChiffre, texteClair, longueurDonnees);
// Chiffrer le texte
Message("CryptEncrypt...\n");
if (!CryptEncrypt(clef,0,TRUE,0,texteChiffre,&longueurDonnees,longueurTexteChiffre))
Erreur("CryptEncrypt");
// Creer un fichier où seront sauvegardées les données chiffrées
Message("CreateFile...\n");
if ((fichierChiffre = CreateFile(nomFichierChiffre, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE)
Erreur("CreateFile");
// Ecrire les données chiffrées dans le fichier
Message("WriteFile...\n");
if (!WriteFile(fichierChiffre, (LPCVOID)texteChiffre, longueurDonnees, &nombreOctetsEcrits, NULL))
Erreur("WriteFile");
// Fermer le fichier de destination
if (fichierChiffre)
{
Message("CloseHandle...\n");
CloseHandle(fichierChiffre);
}
// Fermer le fichier d'origine
if (fichierClair)
{
Message("CloseHandle...\n");
CloseHandle(fichierClair);
}
// Libérer le tampon stockant le bloc de texte
if (texteChiffre)
{
Message("free...\n");
free(texteChiffre);
}
// Libérer le tampon stockant le texte
if (texteClair)
{
Message("free...\n");
free(texteClair);
}
}
void Dechiffrer(char* nomFichierChiffre, char* nomFichierClair)
{
// Déclaration des variables locales
HANDLE fichierClair = 0;
HANDLE fichierChiffre = 0;
LPBYTE texteClair = 0;
LPBYTE texteChiffre = 0;
DWORD longueurTexteClair = 0;
DWORD longueurTexteChiffre = 0;
DWORD nombreOctetsEcrits = 0;
// Ouvrir le fichier chiffré
Message("CreateFile...\n");
if ((fichierChiffre = CreateFile(nomFichierChiffre, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL)) == INVALID_HANDLE_VALUE)
Erreur("CreateFile");
//Obtenir la taille du fichier
Message("GetFileSize...\n");
if ((longueurTexteChiffre = GetFileSize(fichierChiffre, NULL)) == INVALID_FILE_SIZE)
Erreur("GetFileSize");
// Creer une zone tampon pour stocker le texte chiffré
Message("malloc...\n");
if (!(texteChiffre = (BYTE *)malloc(longueurTexteChiffre)))
Erreur("malloc");
// Lire le texte à partir du fichier
Message("ReadFile...\n");
if (!ReadFile(fichierChiffre, texteChiffre, longueurTexteChiffre, &longueurTexteChiffre, NULL))
Erreur("ReadFile");
// Déterminer la taille du tampon de sortie
longueurTexteClair = longueurTexteChiffre;
// Allouer l'espace mémoire pour le tampon de sortie
Message("malloc...\n");
if (!(texteClair = (BYTE *) malloc(longueurTexteClair)))
Erreur("malloc");
// Initialiser tampon de sortie
DWORD longueurDonnees = longueurTexteClair;
memset(texteClair, ' ', longueurTexteClair);
memcpy(texteClair, texteChiffre, longueurDonnees);
// Déchiffrer les données
Message("CryptDecrypt...\n");
if (!CryptDecrypt(clef, NULL, TRUE, 0, texteClair, &longueurDonnees))
Erreur("CryptDecrypt");
// Creer un fichier où seront sauvegardées les données déchiffrées
Message("CreateFile...\n");
if ((fichierClair = CreateFile(nomFichierClair, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE)
Erreur("CreateFile");
// Ecrire les données déchiffrées dans le fichier
Message("WriteFile...\n");
if (!WriteFile(fichierClair, (LPCVOID)texteClair, longueurDonnees, &nombreOctetsEcrits, NULL))
Erreur("WriteFile");
// Fermer le fichier d'origine
if (fichierChiffre)
{
Message("CloseHandle...\n");
CloseHandle(fichierChiffre);
}
// Fermer le fichier de destination
if (fichierClair)
{
Message("CloseHandle...\n");
CloseHandle(fichierClair);
}
// Libérer le tampon stockant le texte
if (texteClair)
{
Message("free...\n");
free(texteClair);
}
// Libérer le tampon stockant le bloc de texte
if (texteChiffre)
{
Message("free...\n");
free(texteChiffre);
}
}
int main(int argc, char* argv[])
{
Message("****************************************"
"\n* Generer une clef et l'exporter dans un fichier\n"
"****************************************");
Initialiser();
GenererClef();
ExporterClef(NOM_FICHIER_CLEF);
Nettoyer();
Message("****************************************\n");
Message("\n****************************************"
"\nImporter la clef a partir d'un fichier, et chiffrer le fichier cible\n"
"****************************************");
Initialiser();
ImporterClef(NOM_FICHIER_CLEF);
Chiffrer(NOM_FICHIER_DATA_CLAIR,NOM_FICHIER_DATA_CHIFFRE);
Nettoyer();
Message("****************************************\n");
Message("\n****************************************"
"\nImporter la clef a partir d'un fichier, et dechiffrer le fichier cible\n"
"****************************************");
Initialiser();
ImporterClef(NOM_FICHIER_CLEF);
Dechiffrer(NOM_FICHIER_DATA_CHIFFRE,NOM_FICHIER_DATA_DECHIFFRE);
Nettoyer();
Message("****************************************\n");
// Permettre à l'utilisateur de visualiser les messages.
system("pause");
}
Vous n'êtes pas encore membre ?
inscrivez-vous, c'est gratuit et ça prend moins d'une minute !
Les membres obtiennent plus de réponses que les utilisateurs anonymes.
Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.
Le fait d'être membre vous permet d'avoir des options supplémentaires.