156 votes

Comment calculer la somme de contrôle MD5 d'un fichier en Python ?

J'ai écrit un code en Python qui vérifie la présence d'un hachage MD5 dans un fichier et s'assure que ce hachage correspond à celui de l'original.

Voici ce que j'ai développé :

# Defines filename
filename = "file.exe"

# Gets MD5 from file 
def getmd5(filename):
    return m.hexdigest()

md5 = dict()

for fname in filename:
    md5[fname] = getmd5(fname)

# If statement for alerting the user whether the checksum passed or failed

if md5 == '>md5 will go here<': 
    print("MD5 Checksum passed. You may now close this window")
    input ("press enter")
else:
    print("MD5 Checksum failed. Incorrect MD5 in file 'filename'. Please download a new copy")
    input("press enter") 
exit

Mais chaque fois que j'exécute le code, j'obtiens l'erreur suivante :

Traceback (most recent call last):
File "C:\Users\Username\md5check.py", line 13, in <module>
 md5[fname] = getmd5(fname)
File "C:\Users\Username\md5check.py, line 9, in getmd5
  return m.hexdigest()
NameError: global name 'm' is not defined

Y a-t-il quelque chose qui manque dans mon code ?

316voto

PSS Points 1098

En ce qui concerne votre erreur et ce qui manque dans votre code. m est un nom qui n'est pas défini pour getmd5() fonction.

Sans vouloir vous offenser, je sais que vous êtes un débutant, mais votre code part dans tous les sens. Examinons vos problèmes un par un :)

Premièrement, vous n'utilisez pas hashlib.md5.hexdigest() correctement. Veuillez vous référer aux explications sur les fonctions hashlib dans Bibliothèque de documentation Python . La manière correcte de renvoyer le MD5 pour les données fournies chaîne de caractères est de faire quelque chose comme ça :

>>> import hashlib
>>> hashlib.md5("example string").hexdigest()
'2a53375ff139d9837e93a38a279d63e5'

Cependant, vous avez un plus gros problème ici. Vous calculez le MD5 sur un chaîne de noms de fichiers alors qu'en réalité, le MD5 est calculé sur la base du fichier. contenu . Vous devrez essentiellement lire le contenu du fichier et le faire passer par MD5. Mon prochain exemple n'est pas très efficace, mais quelque chose comme ça :

>>> import hashlib
>>> hashlib.md5(open('filename.exe','rb').read()).hexdigest()
'd41d8cd98f00b204e9800998ecf8427e'

Comme vous pouvez le voir, le second hachage MD5 est totalement différent du premier. La raison en est que nous faisons passer le contenu du fichier, et pas seulement son nom.

Une solution simple pourrait être quelque chose comme ça :

# Import hashlib library (md5 method is part of it)
import hashlib

# File to check
file_name = 'filename.exe'

# Correct original md5 goes here
original_md5 = '5d41402abc4b2a76b9719d911017c592'  

# Open,close, read file and calculate MD5 on its contents 
with open(file_name, 'rb') as file_to_check:
    # read contents of the file
    data = file_to_check.read()    
    # pipe contents of the file through
    md5_returned = hashlib.md5(data).hexdigest()

# Finally compare original MD5 with freshly calculated
if original_md5 == md5_returned:
    print "MD5 verified."
else:
    print "MD5 verification failed!."

Veuillez consulter l'article Python : Génération d'une somme de contrôle MD5 d'un fichier . Il explique en détail plusieurs façons d'y parvenir efficacement.

Bonne chance.

61voto

Boris Points 1440

En Python 3.8+ vous pouvez faire

import hashlib

with open("your_filename.png", "rb") as f:
    file_hash = hashlib.md5()
    while chunk := f.read(8192):
        file_hash.update(chunk)

print(file_hash.digest())
print(file_hash.hexdigest())  # to get a printable str instead of bytes

Sur Python 3.7 et inférieur :

with open("your_filename.png", "rb") as f:
    file_hash = hashlib.md5()
    chunk = f.read(8192)
    while chunk:
        file_hash.update(chunk)
        chunk = f.read(8192)

print(file_hash.hexdigest())

Ceci lit le fichier 8192 (ou 2¹³) octets à la fois au lieu de tout lire en une seule fois avec f.read() pour utiliser moins de mémoire.


Envisagez d'utiliser hashlib.blake2b au lieu de md5 (il suffit de remplacer md5 avec blake2b dans les extraits ci-dessus). C'est une sécurité cryptographique et plus rapide que MD5.

6voto

liurui39660 Points 41

hashlib Les méthodes prennent également en charge mmap et j'utilise donc souvent le module

from hashlib import md5
from mmap import mmap, ACCESS_READ

path = ...
with open(path) as file, mmap(file.fileno(), 0, access=ACCESS_READ) as file:
    print(md5(file).hexdigest())

path est le chemin d'accès à votre fichier.

Réf : https://docs.python.org/library/mmap.html#mmap.mmap

Edit : Comparaison avec la méthode de lecture en clair.

Plot of time and memory usage

from hashlib import md5
from mmap import ACCESS_READ, mmap

from matplotlib.pyplot import grid, legend, plot, show, tight_layout, xlabel, ylabel
from memory_profiler import memory_usage
from numpy import arange

def MemoryMap():
    with open(path) as file, mmap(file.fileno(), 0, access=ACCESS_READ) as file:
        print(md5(file).hexdigest())

def PlainRead():
    with open(path, 'rb') as file:
        print(md5(file.read()).hexdigest())

if __name__ == '__main__':
    path = ...
    y = memory_usage(MemoryMap, interval=0.01)
    plot(arange(len(y)) / 100, y, label='mmap')
    y = memory_usage(PlainRead, interval=0.01)
    plot(arange(len(y)) / 100, y, label='read')
    ylabel('Memory Usage (MiB)')
    xlabel('Time (s)')
    legend()
    grid()
    tight_layout()
    show()

path est le chemin vers un fichier csv de 3.77GiB.

-2voto

Dilip Dabhade Points 1

Vous pouvez calculer la somme de contrôle d'un fichier en lisant les données binaires et en utilisant la commande hashlib.md5().hexdigest() . Une fonction pour faire cela ressemblerait à ce qui suit :

def File_Checksum_Dis(dirname):

    if not os.path.exists(dirname):
        print(dirname+" directory is not existing");

    for fname in os.listdir(dirname):
        if not fname.endswith('~'):
            fnaav = os.path.join(dirname, fname);
            fd = open(fnaav, 'rb');
            data = fd.read();
            fd.close();

            print("-"*70);
            print("File Name is: ",fname);          
            print(hashlib.md5(data).hexdigest())
            print("-"*70);

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X