2010-02-06 10 views
14

Lors du calcul d'une seule somme de contrôle MD5 sur un fichier volumineux, quelle technique est généralement utilisée pour combiner les différentes valeurs MD5 en une seule valeur? Est-ce que vous venez de les ajouter ensemble? Je ne suis pas vraiment intéressé par une langue, une bibliothèque ou une API particulière qui le fera; Je m'intéresse plutôt à la technique derrière. Quelqu'un peut-il expliquer comment cela est fait?Combinaison des valeurs de hachage MD5

Compte tenu de l'algorithme suivant en pseudo-code:

MD5Digest X 
for each file segment F 
    MD5Digest Y = CalculateMD5(F) 
    Combine(X,Y) 

Mais que serait Combine exactement? Est-ce qu'il ajoute les deux condensés MD5 ensemble, ou quoi?

+0

Pourquoi voudriez-vous faire cela? – AndiDog

+0

Pour calculer les valeurs MD5 pour les fichiers qui sont trop volumineux pour être placés dans la mémoire – channel72

+5

MD5 ne dispose que d'un état de 128 bits qui suit un segment de fichier de 512 bits pendant le calcul; qui se soucie de la taille du fichier? –

Répondre

16

Afin de calculer les valeurs MD5 pour les fichiers qui sont trop volumineux pour tenir dans la mémoire

Avec cela à l'esprit, vous ne voulez pas « combiner » deux hash MD5. Avec toute implémentation MD5, vous avez un objet qui conserve l'état de somme de contrôle en cours. Vous pouvez donc extraire la somme de contrôle MD5 à tout moment, ce qui est très pratique lorsque vous hachez deux fichiers partageant le même début. Pour les gros fichiers, il suffit de continuer à alimenter les données - il n'y a aucune différence si vous hachez le fichier à la fois ou en blocs, car l'état est mémorisé. Dans les deux cas, vous obtiendrez le même hachage.

2

La bibliothèque openSSL vous permet d'ajouter des blocs de données à un hachage en cours (sha1/md5), puis lorsque vous avez fini d'ajouter toutes les données que vous appelez la méthode Final, le hachage final est généré.

Vous ne calculez pas md5 sur chaque bloc, puis ajoutez-le, vous ajoutez plutôt les données à la méthode de hachage en cours à partir de la bibliothèque openssl. Cela vous donnera alors un hachage MD5 de tous les blocs de données individuels sans limite sur la taille des données d'entrée.

http://www.openssl.org/docs/crypto/md5.html#

2

Cette question ne fait pas beaucoup de sens que l'algorithme MD5 prend toute entrée de longueur. Une bibliothèque décente doit avoir des fonctions de sorte que vous n'aurez pas à ajouter le message entier en une seule fois car le message est décomposé en blocs et haché séquentiellement, avec le bloc qui est en cours de traitement en ne dépendant que des hachages résultants du précédent boucle.

Le pseudo-code du wikipedia article devrait donner un aperçu du fonctionnement de l'algorithme.

1

La plupart des implémentations de calcul de résumé permettent de les alimenter en blocs plus petits. Vous ne pouvez pas combiner plusieurs condensés MD5 de telle sorte que le résultat soit égal au MD5 de l'entrée entière. MD5 effectue un certain remplissage et utilise le nombre d'octets traités dans l'étape finale, ce qui rend l'état du moteur d'origine irrécupérable à partir de la valeur de résumé finale.

+0

Donc, ce qui suit est un excellent exemple de la façon de ne pas implémenter plusieurs combinaisons MD5? Cet utilisateur concatène simplement plusieurs hachages individuels pour des blocs individuels d'un fichier volumineux. http://www.postgresql-archive.org/md5-large-object-id-tp5866710p5869128.html –

+0

@Thorsten: Il peut être approprié de concaténer des sommes de hachage de blocs de taille fixe, puis de hacher à nouveau la chaîne concaténée pour obtenir un seul valeur de hachage. La somme de hachage qui en résulte n'est tout simplement pas la même que celle que vous obtiendriez si vous aviez haché le fichier entier. Cela signifie que la concaténation est inutile si vous avez besoin de la comparer avec celle qui n'est pas calculée de cette façon, mais si vous définissez votre propre protocole, vous pouvez décider de définir une certaine taille de bloc et de toujours calculer vos hachages. La qualité du hachage n'est pas pire que la fonction de hachage d'origine. Le partage de fichiers edonkey p2p utilise des hachages comme celui-ci. – x4u

6

MD5 est un algorithme itératif. Vous n'avez pas besoin de calculer une tonne de petits MD5, puis les combiner d'une manière ou d'une autre. Vous venez de lire les petits morceaux du fichier et de les ajouter au résumé alors que vous êtes en train de le faire, vous n'avez donc jamais besoin d'avoir le fichier entier en mémoire à la fois. Voici une implémentation Java.

FileInputStream f = new FileInputStream(new File("bigFile.txt")); 
MessageDigest digest = MessageDigest.getInstance("md5"); 
byte[] buffer = new byte[8192]; 
int len = 0; 
while (-1 != (len = f.read(buffer))) { 
    digest.update(buffer,0,len); 
} 
byte[] md5hash = digest.digest(); 

Et voila. Vous avez le MD5 d'un fichier entier sans jamais avoir le fichier entier en mémoire à la fois.Cela vaut la peine de noter que si, pour une raison ou une autre, vous voulez des hachages MD5 de sous-sections du fichier (cela est parfois utile pour effectuer des contrôles provisoires sur un gros fichier transféré sur une connexion à faible bande passante) les obtenir par clonage l'objet condensé à tout moment, comme si

byte[] interimHash = ((MessageDigest)digest.clone()).digest(); 

Cela n'affecte pas l'objet digérer réel de sorte que vous pouvez continuer à travailler avec le hachage MD5 global. Il convient également de noter que MD5 est un hachage obsolète à des fins de cryptographie (comme la vérification de l'authenticité d'un fichier d'une source non fiable) et devrait être remplacé par quelque chose de mieux dans la plupart des cas, comme SHA-1. À des fins non cryptographiques, telles que la vérification de l'intégrité des fichiers entre deux sources approuvées, MD5 est toujours adéquat.

+0

J'ai un cas d'utilisation pour avoir besoin de sommer les MD5. Je lis plusieurs fichiers en parallèle et souhaite avoir une seule somme de contrôle pour l'ensemble de la collection (en supposant que les fichiers sont classés par ordre alphabétique). – Synesso

1

Voici une façon C# de combiner le hachage. Faisons des méthodes d'extension pour simplifier le code utilisateur.

public static class MD5Append 
{ 
    public static int Append(this MD5 md5, byte[] data) 
    { 
     return md5.TransformBlock(data, 0, data.Length, data, 0); 
    } 

    public static void AppendFinal(this MD5 md5, byte[] data) 
    { 
     md5.TransformFinalBlock(data, 0, data.Length); 
    } 
} 

Utilisation:

using (var md5 = MD5CryptoServiceProvider.Create("MD5")) 
     { 
      md5.Initialize(); 

      var abcBytes = Encoding.Unicode.GetBytes("abc"); 
      md5.Append(abcBytes); 
      md5.AppendFinal(abcBytes); 

      var h1 = md5.Hash; 

      md5.Initialize(); // mandatory 
      var h2= md5.ComputeHash(Encoding.Unicode.GetBytes("abcabc")); 

      Console.WriteLine(Convert.ToBase64String(h1)); 
      Console.WriteLine(Convert.ToBase64String(h2)); 
     } 

h1 et h2 sont les mêmes. C'est tout.

+0

Bienvenue à SO, utilisateur1326493, et merci de votre réponse. – Brian

1

Un exemple Python 2.7 pour la réponse d'AndiDog. Le fichier 123.txt a plusieurs lignes.

>>> import hashlib 
>>> md5_A, md5_B, md5_C = hashlib.md5(), hashlib.md5(), hashlib.md5() 
>>> with open('123.txt', 'r') as f_r: 
...  md5_A.update(f_r.read()) # read whole contents 
... 
>>> with open('123.txt', 'r') as f_r: 
...  for line in f_r: # read file line by line 
...   md5_B.update(line) 
... 
>>> with open('123.txt', 'r') as f_r: 
...  while True: # read file chunk by chunk 
...   chunk = f_r.read(10) 
...   if not chunk: break 
...   md5_C.update(chunk) 
... 
>>> md5_A.hexdigest() 
'5976ddfa19bc2e1669ac3bd836101f58' 
>>> md5_B.hexdigest() 
'5976ddfa19bc2e1669ac3bd836101f58' 
>>> md5_C.hexdigest() 
'5976ddfa19bc2e1669ac3bd836101f58' 

Pour un grand fichier qui ne peut pas tenir dans la mémoire, il peut être lu ligne par ligne ou morceau par morceau. Une utilisation de ce MD5 consiste à comparer deux gros fichiers lorsque la commande diff échoue.