Jak obliczyć sumę kontrolną MD5 pliku w Pythonie?

90

Zrobiłem kod w Pythonie, który sprawdza MD5 w pliku i upewnia się, że MD5 pasuje do oryginału.

Oto, co opracowałem:

#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

Ale za każdym razem, gdy uruchamiam kod, pojawia się następujący błąd:

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

Czy jest coś, czego mi brakuje w moim kodzie?

Dzięki.

user2344996
źródło
1
możliwy duplikat Generowania sumy kontrolnej MD5 pliku?
pylover

Odpowiedzi:

210

W odniesieniu do twojego błędu i tego, czego brakuje w twoim kodzie. mto nazwa, która nie jest zdefiniowana dla getmd5()funkcji.

Bez obrazy, wiem, że jesteś początkującym, ale twój kod jest wszędzie. Spójrzmy kolejno na Twoje problemy :)

Po pierwsze, nie używasz hashlib.md5.hexdigest()poprawnie metody. Proszę zapoznać się z wyjaśnieniem funkcji hashlib w Python Doc Library . Prawidłowym sposobem zwrócenia MD5 dla podanego ciągu jest zrobienie czegoś takiego:

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

Jednak masz tutaj większy problem. Obliczasz MD5 w ciągu nazwy pliku , gdzie w rzeczywistości MD5 jest obliczany na podstawie zawartości pliku . Będziesz musiał po prostu przeczytać zawartość pliku i potokować go przez MD5. Mój następny przykład nie jest zbyt wydajny, ale coś takiego:

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

Jak widać wyraźnie drugi hash MD5 jest zupełnie inny niż pierwszy. Powodem tego jest to, że przepychamy zawartość pliku, a nie tylko jego nazwę.

Prostym rozwiązaniem może być coś takiego:

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

Proszę spojrzeć na post Python: Generating a MD5 checksum of a file . Szczegółowo wyjaśnia kilka sposobów, jak można to skutecznie osiągnąć.

Powodzenia.

PSS
źródło
1
Łał. Czuję się taki zawstydzony. Wydaje mi się, że wstawiłem zły kod do tego, co robiłem, i dodałem do niego wiele błędów. Dzięki za pomoc. Jestem chociaż bardziej przyzwyczajony do batch i lua. Więc Python jest dla mnie wybredny.
user2344996
21
Powinieneś także otworzyć plik w trybie binarnym z open (nazwa_pliku, 'rb'), w przeciwnym razie możesz mieć problemy, gdy system operacyjny wykonuje konwersję powrotu nowej linii / powrotu karetki. Zobacz mail.python.org/pipermail/tutor/2004-J January/027634.html i stackoverflow.com/questions/3431825/ ...
twobeers
4
Jeśli pracujesz nad plikiem binarnym, upewnij się, że czytasz go poprawnie w trybie 'b', w końcu sprawiam, że działa zgodnie z oczekiwaniami z tym: hashlib.sha512 (open (fn, 'rb'). Read ()). Hexdigest ()
Jammy Lee
13

W Pythonie 3.8+ możesz to zrobić

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

W Pythonie 3.7 i starszych:

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

Powoduje to wczytanie pliku o 8192 (lub 2¹³) bajtów na raz zamiast wszystkich naraz, f.read()aby zużywać mniej pamięci.


Rozważyć użycie hashlib.blake2bzamiast md5(wystarczy wymienić md5ze blake2bw powyższych fragmentach). Jest bezpieczny kryptograficznie i szybszy niż MD5.

Boris
źródło
-2

Możesz obliczyć sumę kontrolną pliku, odczytując dane binarne i używając hashlib.md5().hexdigest(). Funkcja służąca do tego wyglądałaby następująco:

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
źródło