Existe-t-il un moyen simple de générer (et de vérifier) les sommes de contrôle MD5 d'une liste de fichiers en Python? (J'ai un petit programme sur lequel je travaille, et je voudrais confirmer les sommes de contrôle des fichiers).
348
md5sum
?md5sum
. C'est pourquoi les programmeurs soucieux de la sécurité ne devraient pas l'utiliser à mon avis.md5sum
et la technique décrite dans cette question SO doivent être évitées - il est préférable d'utiliser SHA-2 ou SHA-3, si possible: en.wikipedia.org/wiki/Secure_Hash_AlgorithmsRéponses:
Vous pouvez utiliser hashlib.md5 ()
Notez que parfois, vous ne pourrez pas mettre le fichier entier en mémoire. Dans ce cas, vous devrez lire séquentiellement des morceaux de 4096 octets et les alimenter à la
md5
méthode:Remarque:
hash_md5.hexdigest()
renverra la représentation de la chaîne hexadécimale pour le résumé, si vous avez juste besoin de l'utilisation des octets compressésreturn hash_md5.digest()
, vous n'avez donc pas à reconvertir.la source
Il y a un moyen qui est assez inefficace en mémoire .
un seul fichier:
liste des fichiers:
Rappelez-vous cependant que MD5 est connu comme cassé et ne doit pas être utilisé à quelque fin que ce soit, car l'analyse de vulnérabilité peut être très délicate, et l'analyse de toute utilisation future possible de votre code pour des problèmes de sécurité est impossible. À mon humble avis, il devrait être retiré de la bibliothèque pour que tous ceux qui l'utilisent soient obligés de mettre à jour. Alors, voici ce que vous devriez faire à la place:
Si vous ne voulez que 128 bits de résumé, vous pouvez le faire
.digest()[:16]
.Cela vous donnera une liste de tuples, chaque tuple contenant le nom de son fichier et son hachage.
Encore une fois, je remets fortement en question votre utilisation de MD5. Vous devriez au moins utiliser SHA1, et compte tenu des failles récentes découvertes dans SHA1 , probablement même pas. Certaines personnes pensent que tant que vous n'utilisez pas MD5 à des fins «cryptographiques», tout va bien. Mais les choses ont tendance à avoir une portée plus large que ce à quoi vous vous attendiez initialement, et votre analyse de vulnérabilité occasionnelle peut s'avérer complètement erronée. Il est préférable de prendre l'habitude d'utiliser le bon algorithme dès le départ. Il suffit de taper un groupe de lettres différent, c'est tout. Ce n'est pas si dur.
Voici un moyen plus complexe, mais efficace en mémoire :
Et, encore une fois, puisque MD5 est cassé et ne devrait plus jamais être utilisé:
Encore une fois, vous pouvez mettre
[:16]
après l'appel àhash_bytestr_iter(...)
si vous ne voulez que 128 bits de résumé.la source
Je n'ajoute clairement rien de fondamentalement nouveau, mais j'ai ajouté cette réponse avant que je ne sois en train de commenter le statut, plus les régions de code rendent les choses plus claires - de toute façon, spécifiquement pour répondre à la question de @ Nemo à partir de la réponse d'Omnifarious:
Je pensais un peu aux sommes de contrôle (je suis venu ici à la recherche de suggestions sur la taille des blocs, en particulier) et j'ai constaté que cette méthode pouvait être plus rapide que ce à quoi vous vous attendiez. Prendre le plus rapide (mais assez typique)
timeit.timeit
ou le/usr/bin/time
résultat de chacune des méthodes de somme de contrôle d'un fichier d'env. 11 Mo:Ainsi, il semble que Python et / usr / bin / md5sum prennent environ 30 ms pour un fichier de 11 Mo. Le pertinent
md5sum
fonction (md5sum_read
dans la liste ci-dessus) est assez similaire à celle d'Omnifarious:Certes, ceux-ci proviennent de cycles uniques (
mmap
ceux-ci sont toujours plus rapides quand au moins quelques dizaines de cycles sont effectués), et le mien a généralement un supplémentf.read(blocksize)
après que le tampon est épuisé, mais il est raisonnablement répétable et montre quemd5sum
sur la ligne de commande est pas nécessairement plus rapide qu'une implémentation Python ...EDIT: Désolé pour le long retard, je n'ai pas regardé cela depuis un certain temps, mais pour répondre à la question de @ EdRandall, je vais écrire une implémentation Adler32. Cependant, je n'ai pas exécuté les repères pour cela. C'est fondamentalement le même que le CRC32 aurait été: au lieu des appels init, update et digest, tout est un
zlib.adler32()
appel:Notez que cela doit commencer avec la chaîne vide, car les sommes d'Adler diffèrent en effet lors du démarrage de zéro par rapport à leur somme pour
""
, ce qui est1
- CRC peut commencer à la0
place. LeAND
-ing est nécessaire pour en faire un entier non signé 32 bits, ce qui garantit qu'il renvoie la même valeur sur toutes les versions de Python.la source
Dans Python 3.8+, vous pouvez faire
Pensez à utiliser
hashlib.blake2b
place demd5
(remplacez simplementmd5
parblake2b
dans l'extrait ci-dessus). Il est cryptographiquement sécurisé et plus rapide que MD5.la source
:=
opérateur est un "opérateur d'affectation" (nouveau dans Python 3.8+); il vous permet d'affecter des valeurs à l'intérieur d'une expression plus grande; plus d'informations ici: docs.python.org/3/whatsnew/3.8.html#assignment-expressionsla source
Je pense que compter sur le paquet invoke et le binaire md5sum est un peu plus pratique que le sous-processus ou le paquet md5
Cela suppose bien sûr que vous ayez invoqué et md5sum installé.
la source
path
s'agit d'un chemin fourni par l'utilisateur, cela permettra à tout utilisateur d'exécuter des commandes bash arbitraires sur votre système.