¿Cómo calculo la suma de comprobación MD5 de un archivo en Python?

84

Hice un código en Python que busca un MD5 en un archivo y se asegura de que el MD5 coincida con el original.

Esto es lo que he desarrollado:

#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

Pero cada vez que ejecuto el código, aparece el siguiente error:

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

¿Hay algo que me falte en mi código?

Gracias.

usuario2344996
fuente

Respuestas:

205

Con respecto a su error y lo que falta en su código. mes un nombre que no está definido para su getmd5()función.

No te ofendas, sé que eres un principiante, pero tu código está por todas partes. Veamos sus problemas uno por uno :)

Primero, no está utilizando el hashlib.md5.hexdigest()método correctamente. Consulte la explicación sobre las funciones de hashlib en la biblioteca de documentos de Python . La forma correcta de devolver MD5 para la cadena proporcionada es hacer algo como esto:

>>> import hashlib
>>> hashlib.md5("filename.exe").hexdigest()
'2a53375ff139d9837e93a38a279d63e5'

Sin embargo, aquí tienes un problema mayor. Está calculando MD5 en una cadena de nombre de archivo , donde en realidad MD5 se calcula en función del contenido del archivo . Tendrá que leer básicamente el contenido del archivo y canalizarlo a través de MD5. Mi siguiente ejemplo no es muy eficiente, pero algo como esto:

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

Como puede ver claramente, el segundo hash MD5 es totalmente diferente al primero. La razón de esto es que estamos empujando el contenido del archivo, no solo el nombre del archivo.

Una solución simple podría ser algo como eso:

# 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) 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!."

Por favor, mire la publicación Python: Generación de una suma de comprobación MD5 de un archivo . Explica en detalle un par de formas de cómo se puede lograr de manera eficiente.

La mejor de las suertes.

PSS
fuente
1
Guau. Me siento tan avergonzado. Supongo que puse el código incorrecto para lo que estaba haciendo y agregué muchos errores junto con él. Gracias por tu ayuda. Aunque estoy más acostumbrado a batch y lua. Entonces Python es exigente para mí.
user2344996
19
También debe abrir el archivo en modo binario con open (file_name, 'rb'), de lo contrario, podría tener problemas cuando el sistema operativo realiza conversiones de retorno de línea / retorno de carro. Ver mail.python.org/pipermail/tutor/2004-January/027634.html y stackoverflow.com/questions/3431825/…
twobeers
4
Si está trabajando en un archivo binario, asegúrese de leerlo correctamente con el modo 'b', finalmente lo hago funcionar como se esperaba con esto: hashlib.sha512 (open (fn, 'rb'). Read ()). Hexdigest ()
Jammy Lee
9

En Python 3.8+ puedes hacer

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

En Python 3.7 y versiones anteriores:

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())

Esto lee el archivo 8192 (o 2¹³) bytes a la vez en lugar de todos a la vez f.read()para usar menos memoria.


Considere usar en hashlib.blake2blugar de md5(simplemente reemplace md5con blake2ben el fragmento anterior). Es criptográficamente seguro y más rápido que MD5.

Boris
fuente
0

Puede calcular la suma de comprobación de un archivo leyendo los datos binarios y usando hashlib.md5().hexdigest(). Una función para hacer esto se vería así:

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);
                
Dilip Dabhade
fuente