Hachage d’un fichier avec Indy

J’aime bien utiliser la bibliothèque Crypto++ pour calculer le hachage d’un fichier. Par contre, des fois il m’arrive de vouloir utiliser cette fonctionnalité sans rien télécharger de plus. Heureusement Indy, qui est inclus dans RAD Studio, nous permet de faire cela facilement.

Dans cet article, on verra comment faire un CRC32, MD5 et SHA1.

En premier, on ajoute les fichiers d’en-têtes:

#include <IdHashCRC.hpp>
#include <IdHashMessageDigest.hpp>
#include <IdHashSHA.hpp>

Pour le CRC32 on ajoute cette méthode:

String __fastcall TForm1::GetHashCRC32(const String AFileName)
{
    String Result;

    TIdHashCRC32* LCrc32 = NULL;
    System::Classes::TFileStream* LFileStream = NULL;
    try
    {
        LCrc32 = new TIdHashCRC32();
        LFileStream = new System::Classes::TFileStream(AFileName,
            fmOpenRead | fmShareDenyWrite);
        const unsigned __int64 LVal = LCrc32->HashValue(LFileStream);
        Result = System::Sysutils::IntToHex(LVal, 8);
    }
    __finally
    {
        delete LFileStream;
        delete LCrc32;
    }

    return Result;
}

Pour le MD5 on ajoute cette méthode:

String __fastcall TForm1::GetHashMD5(const String AFileName)
{
    String Result;

    TIdHashMessageDigest5* LMd5 = NULL;
    System::Classes::TFileStream* LFileStream = NULL;
    try
    {
        LMd5 = new TIdHashMessageDigest5();
        LFileStream = new System::Classes::TFileStream(AFileName,
            fmOpenRead | fmShareDenyWrite);
        Result = LMd5->HashStreamAsHex(LFileStream);
    }
    __finally
    {
        delete LFileStream;
        delete LMd5;
    }

    return Result;
}

Pour le SHA1 on ajoute cette méthode:

String __fastcall TForm1::GetHashSHA1(const String AFileName)
{
    String Result;

    TIdHashSHA1* LSha1 = NULL;
    System::Classes::TFileStream* LFileStream = NULL;
    try
    {
        LSha1 = new TIdHashSHA1();
        LFileStream = new System::Classes::TFileStream(AFileName,
            fmOpenRead | fmShareDenyWrite);
        Result = LSha1->HashStreamAsHex(LFileStream);
    }
    __finally
    {
        delete LFileStream;
        delete LSha1;
    }

    return Result;
}

Il est à noter que Indy supporte aussi ces classes:

  • TIdHashSHA224
  • TIdHashSHA256
  • TIdHashSHA384
  • TIdHashSHA512

Pour tester le code, on peut ajouter un contrôle TMemo et mettre le code suivant dans le constructeur.

    const String LFileName = "C:\\monfichier.xyz"; // Le fichier doit exister
    Memo1->Lines->Add("CRC32: " + GetHashCRC32(LFileName));
    Memo1->Lines->Add("MD5  : " + GetHashMD5(LFileName));
    Memo1->Lines->Add("SHA1 : " + GetHashSHA1(LFileName));

Si on veut être certain que le résultat est valide, on peut vérifier avec un logiciel comme HashTab:
HashTab