hashlib - Hashing Crittografico
Scopo: hash crittografici ed impronte di messaggi
Il modulo hashlib definisce una API per accedere a diversi algoritmi crittografici. Per lavorare con uno specifico algoritmo, si usi l'appropriata funzione costruttore oppure new()
per creare un oggetto hash. Da qui, gli oggetti usano la stessa API, non importa quale algoritmo venga usato.
Algoritmi Hash
Visto che hashlib è supportata da OpenSSL, tutti gli algoritmi forniti da quella libreria sono disponibili, compresi:
- md5
- sha1
- sha224
- sha256
- sha384
- sha512
Alcuni algoritmi sono disponibili su tutte le piattaforme, ed alcuni dipendono dalle librerie sottostanti. Per una lista di ognuno, si cerchi rispettivamente in algorithms_guaranteed
e algorithms_avaliable
.
# hashlib_algorithms.py
import hashlib
print('Garantiti:\n{}\n'.format(
', '.join(sorted(hashlib.algorithms_guaranteed))))
print('Disponibili:\n{}'.format(
', '.join(sorted(hashlib.algorithms_available))))
$ python3 hashlib_algorithms.py Garantiti: blake2b, blake2s, md5, sha1, sha224, sha256, sha384, sha3_224, sha3_256, sha3_384, sha3_512, sha512, shake_128, shake_256 Disponibili: blake2b, blake2s, md4, md5, md5-sha1, ripemd160, sha1, sha224, sha256, sha384, sha3_224, sha3_256, sha3_384, sha3_512, sha512, sha512_224, sha512_256, shake_128, shake_256, sm3, whirlpool
Dati Campione
Tutti gli esempi in questa sezione usano gli stessi dati campione.
# hashlib_data.py
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.'''
Esempio MD5
Per calcolare l'hash MD5, o digest (impronta di messaggio), per un blocco di dati (qui una stringa unicode convertita in stringa di byte), prima si crei l'oggetto hash, poi si aggiungano i dati e si chiami digest()
oppure hexdigest()
.
# hashlib_md5.py
import hashlib
from hashlib_data import lorem
h = hashlib.md5()
h.update(lorem.encode('utf-8'))
print(h.hexdigest())
Questo esempio usa il metodo hexdigest()
invece che digest()
visto che il risultato è formattato in modo che possa essere stampato con chiarezza. Se è accettabile un valore di digest binario si usi digest()
.
$ python3 hashlib_md5.py 3f2fd2c9e25d60fb0fa5d593b802b7a8
Esempio SHA1
Una impronta di messaggio SHA1 viene calcolata nello stesso modo.
# hashlib_sha1.py
import hashlib
from hashlib_data import lorem
h = hashlib.sha1()
h.update(lorem.encode('utf-8'))
print(h.hexdigest())
Il valore dell'impronta di messaggio è diverso in questo esempio, visto che l'algoritmo è passato da MD5 a SHA1.
$ python3 hashlib_sha1.py ea360b288b3dd178fe2625f55b2959bf1dba6eef
Creare un hash per Nome
Talvolta è più conveniente riferirsi all'algoritmo per nome in una stringa in luogo di usare la funzione costruttore direttamente. E' utile, ad esempio, essere in grado di conservare il tipo di hash in un file di configurazione. In questi casi, si usi new()
per creare un calcolatore di hash.
# hashlib_new.py
import argparse
import hashlib
import sys
from hashlib_data import lorem
parser = argparse.ArgumentParser('demo hashlib')
parser.add_argument(
'hash_name',
choices=hashlib.algorithms_available,
help="il nome dell'algoritmo da usare per l'hash",
)
parser.add_argument(
'data',
nargs='?',
default=lorem,
help="i dati in input per l'hash, predefinito lorem ipsum",
)
args = parser.parse_args()
h = hashlib.new(args.hash_name)
h.update(args.data.encode('utf-8'))
print(h.hexdigest())
Quando eseguito con diversi argomenti:
$ python3 hashlib_new.py sha1 ea360b288b3dd178fe2625f55b2959bf1dba6eef
$ python3 hashlib_new.py sha256 3c887cc71c67949df29568119cc646f46b9cd2c2b39d456065646bc2fc09ffd8
$ python3 hashlib_new.py sha512 a7e53384eb9bb4251a19571450465d51809e0b7046101b87c4faef96b9bc904cf7f90035f444952dfd9f6084eeee2457433f3ade614712f42f80960b2fca43ff
$ python3 hashlib_new.py md5 3f2fd2c9e25d60fb0fa5d593b802b7a8
Aggiornamenti Incrementali
Il metodo update()
dei calcolatori di hash può essere chiamato ripetutamente. Ogni volta, l'impronta di messaggio viene aggiornata in base al testo addizionale inserito. L'aggiornamento incrementale è più efficiente rispetto alla lettura dell'intero file in memoria, e produce lo stesso risultato.
# hashlib_update.py
import hashlib
from hashlib_data import lorem
h = hashlib.md5()
h.update(lorem.encode('utf-8'))
all_at_once = h.hexdigest()
def chunkize(size, text):
"Ritorna parti di testo con incrementi in base alla dimensione."
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.encode('utf-8')):
h.update(chunk)
line_by_line = h.hexdigest()
print('Tutto in una volta:', all_at_once)
print('Riga per Riga :', line_by_line)
print('Verifica :', (all_at_once == line_by_line))
Questo esempio dimostra come aggiornare in modo incrementale una impronta di messaggio mano a mano che i dati vengono letti o prodotti in altro modo.
$ python3 hashlib_update.py Tutto in una volta: 3f2fd2c9e25d60fb0fa5d593b802b7a8 Riga per Riga : 3f2fd2c9e25d60fb0fa5d593b802b7a8 Verifica : True
Vedere anche:
- hashlib
- La documentazione della libreria standard per questo modulo.
- hmac
- Il modulo hmac
- OpenSSL
- Un pacchetto di strumenti open source per la crittografia.
- Cryptography
- Un pacchetto Python che fornisce primitivi e ricette crittografiche.
- Voidspace: IronPython and hashlib
- Un wrapper per hashlib che funziona con IronPython.