La génération d'une somme de contrôle MD5 d'un fichier
Est-il un moyen simple de produire (et de la vérification) somme de contrôle MD5 d'une liste de fichiers en Python? (J'ai un petit programme que je suis en train de travailler sur, et je tiens à confirmer les sommes de contrôle des fichiers).
- Pourquoi ne pas simplement utiliser les
md5sum
? - En gardant en Python rend plus facile la gestion de la compatibilité multiplate-forme.
- Si vous voulez de la solution avec la "barre de progression* ou similaire (pour les très gros fichiers), envisager cette solution: stackoverflow.com/questions/1131220/...
- Le lien que vous avez fourni le dit dans le deuxième paragraphe: "Le sous-jacent algorithme MD5 est plus considéré comme sûr" tout en décrivant
md5sum
. C'est pourquoi, soucieux de la sécurité des programmeurs ne doivent pas l'utiliser à mon avis. - Bon et valable. Les deux
md5sum
et de la technique décrite dans la présente DONC, la question doit être évitée - il est préférable d'utiliser SHA-2 ou SHA-3, si possible: en.wikipedia.org/wiki/Secure_Hash_Algorithms
Vous devez vous connecter pour publier un commentaire.
Vous pouvez utiliser hashlib.md5()
Noter que, parfois, vous ne serez pas en mesure de s'adapter à l'ensemble du fichier en mémoire. Dans ce cas, vous aurez à lire des morceaux de 4096 octets de façon séquentielle et de les nourrir à la fonction Md5:
Remarque:
hash_md5.hexdigest()
sera de retour le chaîne hexadécimale de représentation pour le résumé, si vous avez juste besoin les paniers octets utilisationreturn hash_md5.digest()
, de sorte que vous n'avez pas à convertir en arrière.Il y a un moyen qui est à peu de la mémoire inefficace.
seul fichier:
liste des fichiers:
Rappeler cependant, que MD5 est connu cassé et ne doit pas être utilisé pour n'importe quel but, depuis l'analyse de la vulnérabilité peut être vraiment difficile, et l'analyse d'un avenir possible d'utiliser votre code pourrait être mis à pour les questions de sécurité est impossible. À mon humble avis, il devrait être à plat retirés de la bibliothèque et donc tout le monde qui utilise, il est forcé de mettre à jour. Donc, voici ce que vous devez faire à la place:
Si vous ne voulez 128 bits de la valeur de digérer que vous pouvez faire
.digest()[:16]
.Cela vous donnera une liste de tuples, chaque tuple contenant le nom de son fichier et son hachage.
Je l'ai de nouveau fortement question de votre utilisation de MD5. Vous devez être au moins en utilisant SHA1, et compte tenu de les récentes failles découvertes dans SHA1, probablement même pas que. Certaines personnes pensent que, tant que vous n'êtes pas à l'aide de MD5 pour "cryptographique", vous êtes beaux. Mais les choses ont tendance à finir par être une portée plus large que prévu initialement, et votre décontracté analyse de la vulnérabilité peut s'avérer complètement bancal. Il suffit de prendre l'habitude de l'utilisation de l'algorithme de droite de la porte. C'est juste en tapant un autre des tas de lettres est tout. Il n'est pas difficile.
Ici est une façon qui est plus complexe, mais mémoire efficace:
Et, de nouveau, depuis MD5 est cassé et ne devrait pas vraiment être jamais plus utilisés:
Encore une fois, vous pouvez mettre
[:16]
après l'appel àhash_bytestr_iter(...)
si vous ne voulez 128 bits vaut la peine de digérer.open
. Je crois que c'est travaillé depuis hashlib a été introduit, et a toujours travaillé. Les vieilles habitudes ont la vie dure.hexdigest
de la norme hashlib fonction de hachage de l'interface. Je pense qu'il est inutile de verrue. Et j'aime faire de même de petites fonctions largement applicable. Il existe de nombreux cas dans lesquels l'hex de la table de hachage est tout à fait inutilement bavard et le plus facile à utiliser version est d'encourager les gens à être en clair quand ils n'ont pas à l'être. Mais oui, dans ce cas, pour ce but précis, il est probablement le meilleur choix. Je voudrais encore suffit d'utiliserbinascii.hexlify
à la place. 🙂def hashfile
la fonction ci-dessus à plusieurs reprises sur le même descripteur de fichier n'oubliez pas de réinitialiser leafile
pointeur lorsque vous faites la lecture de chaque fichier. par exemple.afile.seek(0)
mode=rb
? Ne devrait pasrt
simplement de convertir les sauts de ligne et autrement identique àrb
? (Je suppose que c'est python 2, car en python 3hashlib.md5
nécessitebytes
, et vont tout simplement refuser d'accepter une chaîne)hashfile
bien, c'est plus souple car il gère tout ce qui aread
.hashlib.md5(open(full_path, 'rb').read()).hexdigest()
est assez bon. Merci!with
déclaration à l'intérieur defile_as_blockiter
.import hashlib [(fname, hashlib.md5(open(fname, 'rb').read()).digest()) for fname in fnamelst]
Je suis clairement pas en ajoutant quelque chose de fondamentalement nouveau, mais il a ajouté que cette réponse avant j'étais à commenter le statut, plus le code des régions de rendre les choses plus clairement, de toute façon, spécifiquement pour répondre à @Nemo est question de Omnifarious réponse:
Il m'est arrivé de penser au sujet de sommes un peu (venu ici à la recherche de suggestions sur les tailles de bloc, plus précisément), et ont constaté que cette méthode peut être plus rapide que ce que vous attendez. La prise de la manière la plus rapide (mais assez typique)
timeit.timeit
ou/usr/bin/time
en raison de plusieurs méthodes de calcul des sommes de contrôle d'un fichier d'env. 11MB:Alors, ressemble Python et /usr/bin/md5sum prendre environ 30ms pour un 11MO fichier. Pertinentes
md5sum
fonction (md5sum_read
dans la liste ci-dessus) est assez similaire à Omnifarious de l':Accordée, ce sont de simples pistes (la
mmap
sont toujours à imposer un brin plus rapide lorsqu'au moins une douzaine de séries sont faites), et la mienne est généralement un supplément def.read(blocksize)
après le tampon est épuisé, mais il est assez répétitif et montre quemd5sum
sur la ligne de commande n'est pas nécessairement plus rapide qu'un Python de mise en œuvre...EDIT: Désolé pour le retard, n'ont pas regardé ce que dans quelques temps, mais pour répondre à @EdRandall de la question, je vais écrire une Adler32 mise en œuvre. Cependant, je n'ai pas couru les critères de référence pour elle. C'est essentiellement le même que le CRC32 aurait été: au lieu de l'init, mise à jour, et de digérer les appels, tout est une
zlib.adler32()
appel:Notez que cela doit commencer avec la chaîne vide, comme Adler sommes diffèrent en effet lors du démarrage à partir de zéro par rapport à leur somme pour
""
, qui est1
-- CRC pouvez commencer avec0
à la place. LeAND
-ing qui est nécessaire pour rendre un 32 bits entier non signé, qui fait d'elle retourne la même valeur à travers les versions de Python.