Scopo | Hash crittografici e digest del messaggio |
Versione Python | 2.5 |
A partire dal 1 gennaio 2021 le versioni 2.x di Python non sono piu' supportate. Ti invito a consultare la corrispondente versione 3.x dell'articolo per il modulo hashlib
Il modulo hashlib depreca i moduli separati md5 e sha e rende le loro API consistenti. Per lavorare con uno specifico algoritmo hash, si usa la funzione appropriata del costruttore per creare un oggetto hash. Quindi si può usare la stessa API per interagire con l'hash a prescindere dall'algoritmo che è stato usato.
Visto che hashlib è "supportato" da OpenSSL, tutti gli algoritmi forniti da quella libreria dovrebbero essere disponibili, incluso:
Tutti gli esempi seguenti usano lo stesso campione di dati:
import hashlib
lorem = '''Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim
veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum
dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident,
sunt in culpa qui officia deserunt mollit anim id est laborum.'''
Per calcolare il digest MD5 per un blocco di dati (in questo caso una stringa ASCII), si crea l'hash, si aggiungono i dati, quindi si calcola il digest:
import hashlib
from hashlib_data import lorem
h = hashlib.md5()
h.update(lorem)
print h.hexdigest()
Questo esempio usa il metodo
hexdigest()
invece di
digest()
, perchè il risultato viene formattato per essere stampato. Se fosse accettabile un valore binario, si può usare
digest()
.
$ python hashlib_md5.py c3abe541f361b1bfbbcfecbf53aad1fb
Un digest SHA1 per gli stessi dati dovrebbe essere calcolato pressochè allo stesso modo:
import hashlib
from hashlib_data import lorem
h = hashlib.sha1()
h.update(lorem)
print h.hexdigest()
Naturalmente il valore di digest è diverso a causa dell'algoritmo differente.
$ python hashlib_sha1.py ac2a96a4237886637d5352d606d7a7b6d7ad2f29
Qualche volta è più conveniente fare riferimento all'algoritmo per nome in una stringa piuttosto che usare direttamente la funzione del costruttore. E' utile, ad esempio, potere salvare il tipo di hash in un file di configurazione. In questi casi, si usa la funzione
new()
per creare direttamente un nuovo calcolatore di hash.
import hashlib
import sys
try:
hash_name = sys.argv[1]
except IndexError:
print "Specificare il nome dell'hash come primo parametro."
else:
try:
data = sys.argv[2]
except IndexError:
from hashlib_data import lorem as data
h = hashlib.new(hash_name)
h.update(data)
print h.hexdigest()
Quando viene eseguito con diversi parametri:
$ python hashlib_new.py sha1 ac2a96a4237886637d5352d606d7a7b6d7ad2f29
$ python hashlib_new.py sha256 88b7404fc192fcdb9bb1dba1ad118aa1ccd580e9faa110d12b4d63988cf20332
$ python hashlib_new.py sha512 f58c6935ef9d5a94d296207ee4a7d9bba411539d8677482b7e9d60e4b7137f68d25f9747cab62fe752ec5ed1e5b2fa4cdbc8c9203267f995a5d17e4408dccdb4
$ python hashlib_new.py md5 c3abe541f361b1bfbbcfecbf53aad1fb
Il metodo dei calcolatori hash
update()
può essere chiamato ripetutamente. Ogni volta, il digest viene aggiornato in base al testo addizionale immesso. La qual cosa può essere più efficiente del leggere un intero file in memoria, ad esempio:
import hashlib
from hashlib_data import lorem
h = hashlib.md5()
h.update(lorem)
all_at_once = h.hexdigest()
def chunkize(size, text):
"Restituisce parti del testo con incrementi in base alla dimensione di size."
start = 0
while start < len(text):
chunk = text[start:start+size]
yield chunk
start += size
return
h = hashlib.md5()
for chunk in chunkize(64, lorem):
h.update(chunk)
line_by_line = h.hexdigest()
print 'Tutto insieme:', all_at_once
print 'Riga per riga:', line_by_line
print 'Uguale :', (all_at_once == line_by_line)
Questo esempio è un poco sacrificato perchè lavora con una piccolissima porzione di testo, ma illustra come si possa eseguire un aggiornamento incrementale di un digest mentre i dati vengono letti o prodotti in altro modo.
Tutto insieme: c3abe541f361b1bfbbcfecbf53aad1fb Riga per riga: 130c2769a7a3ec3dacf29453986923cb Uguale : False
Vedere anche: