3
votes

Python Compare fichier local et distant MD5 Hash

J'essaie de comparer le hachage MD5 du fichier local et distant (le même fichier que je copie / colle dans mon répertoire wamp "www"), mais je ne comprends pas pourquoi les "sommes de contrôle" ne correspondent pas ...

Voici le code de la somme de contrôle:

checksum_local : f71dbe52628a3f83a77ab494817525c6
checksum_remote : f71dbe52628a3f83a77ab494817525c6

Et je suis surpris d’obtenir ce résultat:

print "checksum_local :",md5Checksum("toto.txt",None)
print "checksum_remote :",md5Checksum(None,"http://testpangya.ddns.net/toto.txt")

La taille de "projectg715gb .pak "fait 14,7 Mo

Mais si j'essaie avec un fichier texte (taille 1 Ko):

checksum_local : 9d33806fdebcb91c3d7bfee7cfbe4ad7
checksum_remote : a13aaeb99eb020a0bc8247685c274e7d

Ensuite, cela fonctionne oO j'obtiens cette sortie:

#-*- coding: utf-8 -*-

import hashlib
import requests

def md5Checksum(filePath,url):
    if url==None:
        with open(filePath, 'rb') as fh:
            m = hashlib.md5()
            while True:
                data = fh.read(8192)
                if not data:
                    break
                m.update(data)
            return m.hexdigest()
    else:
        r = requests.get(url, stream=True)
        m = hashlib.md5()
        for line in r.iter_lines():
            m.update(line)
        return m.hexdigest()

print "checksum_local :",md5Checksum("projectg715gb.pak",None)
print "checksum_remote :",md5Checksum(None,"http://testpangya.ddns.net/projectg715gb.pak")

Je suis nouveau dans la comparaison du hachage MD5 alors soyez gentil s'il vous plaît ^^ 'J'ai peut-être fait une grosse erreur, je ne comprends pas pourquoi ça ne marche pas fichiers, si quelqu'un pouvait me donner un indice, ce serait super sympa!

Cependant, merci d'avoir lu et aidé!


4 commentaires

Dans l'un, vous lisez 8192 octets à la fois, dans l'autre, vous lisez toute la ligne. Les longueurs de ligne ne sont probablement pas exactement 8192 octets. Mettez simplement à jour fh.read (8192) en fh.readline ()


@NickChapman J'ai essayé, donc si j'imprime les données et la ligne, cela semble plus similaire mais les sommes de contrôle sont toujours différentes: '(


.iter_lines () sur la version d'url supprime tous les caractères de nouvelle ligne des données. Utilisez .iter_content () pour le lire en morceaux, tout comme la version du fichier.


Merci !!! @jasonharper Fonctionne bien ^^


3 Réponses :


4
votes

Merci donc aux assistants, voici le code final qui fonctionne:

#-*- coding: utf-8 -*-

import hashlib
import requests

def md5Checksum(filePath,url):
    m = hashlib.md5()
    if url==None:
        with open(filePath, 'rb') as fh:
            m = hashlib.md5()
            while True:
                data = fh.read(8192)
                if not data:
                    break
                m.update(data)
            return m.hexdigest()
    else:
        r = requests.get(url)
        for data in r.iter_content(8192):
             m.update(data)
        return m.hexdigest()

print "checksum_local :",md5Checksum("projectg715gb.pak",None)
print "checksum_remote :",md5Checksum(None,"http://testpangya.ddns.net/projectg715gb.pak")


0 commentaires

1
votes

Merci d'avoir publié votre solution https://stackoverflow.com/users/7495742/framb-axa Était super utile pour mon problème.

J'ai légèrement révisé la partie md5 et les instructions d'impression pour python3 et les ai échangées pour utiliser sha256 pour mon utilisation et cela fonctionne très bien pour mes besoins de télécharger / vérifier un fichier local et Remote SQLite DB pour une application que j'ai créée. Laisser le code ici ainsi que comme référence pour toute autre personne qui pourrait également tomber sur ce message.

import hashlib
import requests


# current release version url
current_release_url = 'https://somedomain.here/current_release.txt'
current_release_notes_url = 'https://somedomain.here/current_release_notes.txt'

# current database release  version url
current_db_release_url = 'https://somedomain.here/current_db_release.txt'
current_db_release_notes_url = 'https://somedomain.here/current_db_release_notes.txt'
current_db_release_notes_hash_url = 'https://somedomain.here/current_db_release_hash.txt'
current_db_release = ''
wizard_db_version = ''

# Default commands DB url
wizard_cmd_db_url = 'https://somedomain.here/sqlite.db'

wizard_cmd_db = 'some/path'

checksum_local = ''
checksum_remote = ''
checksum_remote_hash = ''
checksum_status = ''


def download_cmd_db():
    try:
        print('Downloading database update version: ' + str(current_db_release))
        url = wizard_cmd_db_url
        r = requests.get(url)
        with open(wizard_cmd_db, 'wb') as f:
            f.write(r.content)

        # Retrieve HTTP meta-data
        print(r.status_code)
        # print(r.headers['content-type'])
        # print(r.encoding)
        settings.setValue('wizard_db_version', current_db_release)
        print('Database downloaded to:' + str(wizard_cmd_db))
    except:
        print('Commands Database download failed.... ;( ')


def sha256_checksum(filepath, url):
    m = hashlib.sha256()
    if url is None:
        with open(filepath, 'rb') as fh:
            m = hashlib.sha256()
            while True:
                data = fh.read(8192)
                if not data:
                    break
                m.update(data)
            return m.hexdigest()
    else:
        r = requests.get(url)
        for data in r.iter_content(8192):
            m.update(data)
        return m.hexdigest()


def wizard_db_hash_check():
    global checksum_local, checksum_remote, checksum_status
    try:
        checksum_local = sha256_checksum(wizard_cmd_db, None)
        checksum_remote = sha256_checksum(None, wizard_cmd_db_url)
        print("checksum_local : " + checksum_local)
        print("checksum_remote: " + checksum_remote)
        print("checksum_remote_hash: " + checksum_remote_hash)

        if checksum_local == checksum_remote_hash:
            print('Hash Check passed')
            checksum_status = True
        else:
            print('Hash Check Failed')
            checksum_status = False
    except:
        print('Could not perform wizard_db_hash_check')


# Sanity check for missing database file
file = pathlib.Path(wizard_cmd_db)
if file.exists():
    print("DB File exists: " + wizard_cmd_db)
    wizard_db_hash_check()
else:
    print("DB File does NOT exist: " + wizard_cmd_db)
    download_cmd_db()
    wizard_db_hash_check()

# Check hash

# # Logic to decide when to download DB here
try:
    if int(current_db_release) > int(wizard_db_version):
        print('Database update available: ' + str(current_db_release))
        download_cmd_db()
        wizard_db_hash_check()
except:
    print('Unable to check wizard_db_release')

if checksum_local != checksum_remote:
    download_cmd_db()
    wizard_db_hash_check()

# Logic to fallback to default packaged DB if no internet to download and compare hash
if checksum_status is True:
    target_db = str(wizard_cmd_db)
else:
    print('All hash checks and attempts to update commands DB have failed. Switching to bundled DB')
    target_db = os.path.join(os.path.abspath(os.path.dirname(sys.argv[0])), "sqlite.db")

print('Sanity Checks completed')


3 commentaires

Le seul problème que j'ai maintenant est que lorsque j'essaie cette solution sur un serveur distant, il faudra beaucoup de temps pour obtenir la somme de contrôle md5 du fichier distant ....: (((


Oui, ce sera le cas si le fichier distant est volumineux, car il doit le télécharger entièrement pour vérifier le hachage. S'il s'agit d'un fichier distant sur un serveur que vous contrôlez, vous pouvez également obtenir la somme via ssh facilement. J'utilise ce qui suit pour obtenir le hachage sur ssh car le hachage est ensuite effectué sur le serveur. Ce n'est pas idéal pour confirmer le hachage de votre fichier local, mais fonctionne simplement pour voir ce qu'il devrait être. ssh username @ someserver "sha256sum / home / some / path / to / file"


J'ai trouvé un autre moyen de le faire, il suffit de regarder la réponse suivante :)



1
votes

Ok, on dirait que j'ai trouvé une solution, je la posterai donc ici :)

Vous devez d'abord éditer un fichier .htaccess dans le répertoire où se trouvent vos fichiers sur votre serveur. p>

Contenu du fichier .htaccess :

checksum_local : 7dVTxeHRktvI0Wh/7/4ZOQ==
checksum_remote : 7dVTxeHRktvI0Wh/7/4ZOQ==
The soft don't download the file

Maintenant que vous avez configuré cela, le serveur doit envoyer Content- MD5 dans l'en-tête HTTP.

Cela donnera quelque chose comme:

#-*- coding: utf-8 -*-

import hashlib
import requests
import base64

def md5Checksum(filePath,url):
    m = hashlib.md5()
    if url==None:
        with open(filePath, u'rb') as fh:
            m = hashlib.md5()
            while True:
                data = fh.read(8192)
                if not data:
                    break
                m.update(data)
            #Get BASE 64 Local File md5
            return base64.b64encode(m.digest()).decode('ascii')#Encode MD5 digest to BASE 64
            
    else:
        #Get BASE 64 Remote File md5
        r = requests.head(url) #You read HTTP Header here
        return r.headers['Content-MD5'] #Take only Content-MD5 string

def compare():
    local = md5Checksum("projectg502th.pak.zip",None)
    remote = md5Checksum(None,"http://127.0.0.1/md5/projectg502th.pak.zip")

    if local == remote :
        print("The soft don't download the file")
    else:
        print("The soft download the file")

print ("checksum_local :",md5Checksum("projectg_ziinf.pak.zip",None))
print ("checksum_remote : ",md5Checksum(None,"http://127.0.0.1/md5/projectg_ziinf.pak.zip"))

compare()

Ok maintenant voyons la partie Python, j'ai donc modifié mon code pour pouvoir comparer ces données d'en-tête HTTP et la somme de contrôle md5 locale.

'Content-MD5': '7dVTxeHRktvI0Wh/7/4ZOQ=='

Sortie:

ContentDigest On

J'espère aidera;)


2 commentaires

J'ai fait des tests sur Apache 2.4.4 sur WAMP.


C'est assez dur à cuire. Je ne savais pas que vous pouviez le faire via htaccess. J'utilisais un fichier json hébergé sur le serveur pour obtenir la bonne somme de contrôle connue du fichier distant sans avoir à le télécharger pour le comparer. Cette approche peut également vous plaire si vous la analysez dans votre application. Voir mon lien ci-dessous si curieux pourrait être une autre approche que vous pouvez adopter pour publier et maintenir la somme de contrôle de hachage connue. J'avais un tas de fichiers et j'ai donc fini par se combiner en un seul json à extraire dans l'application. https://wizardassistant.com/wizardassistant_app_current_rele‌ ase_url.json