web-dev-qa-db-fra.com

Calculer la somme de contrôle MD5 pour un fichier

J'utilise iTextSharp pour lire le texte d'un fichier PDF. Cependant, il est parfois impossible d'extraire du texte, car le fichier PDF ne contient que des images. Je télécharge les mêmes fichiers PDF tous les jours et je souhaite vérifier si le fichier PDF a été modifié. Si le texte et la date de modification ne peuvent pas être obtenus, une somme de contrôle MD5 est-elle le moyen le plus fiable de savoir si le fichier a été modifié?

Si c'est le cas, des exemples de code seraient appréciés, car je n'ai pas beaucoup d'expérience en cryptographie.

307
broke

C'est très simple d'utiliser System.Security.Cryptography.MD5 :

using (var md5 = MD5.Create())
{
    using (var stream = File.OpenRead(filename))
    {
        return md5.ComputeHash(stream);
    }
}

(Je crois que en réalité la mise en œuvre MD5 utilisée n'a pas besoin d'être supprimée, mais je le ferais probablement quand même.)

Comment vous comparez les résultats ensuite dépend de vous; Vous pouvez par exemple convertir le tableau d'octets en base64 ou comparer directement les octets. (Sachez simplement que les tableaux ne remplacent pas Equals. Il est plus simple d'utiliser Base64, mais légèrement moins efficace si vous ne voulez vraiment comparer que les hachages.)

Si vous devez représenter le hachage sous forme de chaîne, vous pouvez le convertir en hexadécimal en utilisant BitConverter:

static string CalculateMD5(string filename)
{
    using (var md5 = MD5.Create())
    {
        using (var stream = File.OpenRead(filename))
        {
            var hash = md5.ComputeHash(stream);
            return BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant();
        }
    }
}
701
Jon Skeet

Voici comment je le fais:

using System.IO;
using System.Security.Cryptography;

public string checkMD5(string filename)
{
    using (var md5 = MD5.Create())
    {
        using (var stream = File.OpenRead(filename))
        {
            return Encoding.Default.GetString(md5.ComputeHash(stream));
        }
    }
}
65
BoliBerrys

Je sais que cette question a déjà été répondue, mais voici ce que j'utilise:

using (FileStream fStream = File.OpenRead(filename)) {
    return GetHash<MD5>(fStream)
}

GetHash:

public static String GetHash<T>(Stream stream) where T : HashAlgorithm {
    StringBuilder sb = new StringBuilder();

    MethodInfo create = typeof(T).GetMethod("Create", new Type[] {});
    using (T crypt = (T) create.Invoke(null, null)) {
        byte[] hashBytes = crypt.ComputeHash(stream);
        foreach (byte bt in hashBytes) {
            sb.Append(bt.ToString("x2"));
        }
    }
    return sb.ToString();
}

Ce n'est probablement pas la meilleure solution, mais cela peut être pratique.

7
Badaro Jr.

Et si vous devez calculer le MD5 pour voir s'il correspond au MD5 d'un blob Azure, alors cette SO question et réponse pourraient être utiles: Le hachage MD5 du blob téléchargé sur Azure ne correspond pas à même fichier sur la machine locale

3
Manfred

Voici une version un peu plus simple que j'ai trouvée. Il lit l'intégralité du fichier en une fois et ne nécessite qu'une seule directive using.

byte[] ComputeHash(string filePath)
{
    using (var md5 = MD5.Create())
    {
        return md5.ComputeHash(File.ReadAllBytes(filePath));
    }
}
2
Ashley Davis

Je sais que je suis en retard pour faire la fête mais que j'ai effectué un test avant de réellement mettre en œuvre la solution.

J'ai effectué un test contre la classe MD5 intégrée et aussi md5sum.exe . Dans mon cas, la classe intégrée a pris 13 secondes, alors que md5sum.exe a également tourné autour de 16 à 18 secondes à chaque exécution.

    DateTime current = DateTime.Now;
    string file = @"C:\text.iso";//It's 2.5 Gb file
    string output;
    using (var md5 = MD5.Create())
    {
        using (var stream = File.OpenRead(file))
        {
            byte[] checksum = md5.ComputeHash(stream);
            output = BitConverter.ToString(checksum).Replace("-", String.Empty).ToLower();
            Console.WriteLine("Total seconds : " + (DateTime.Now - current).TotalSeconds.ToString() + " " + output);
        }
    }
0
Romil Kumar Jain