hashlib — Sichere Hashes und Nachrichten-Digests¶
Quellcode: Lib/hashlib.py
Dieses Modul implementiert eine gemeinsame Schnittstelle zu vielen verschiedenen Hash-Algorithmen. Enthalten sind die FIPS-sicheren Hash-Algorithmen SHA224, SHA256, SHA384, SHA512 (definiert im FIPS 180-4 Standard), die SHA-3-Serie (definiert im FIPS 202 Standard) sowie die älteren Algorithmen SHA1 (früher Teil von FIPS) und der MD5-Algorithmus (definiert im Internet RFC 1321).
Hinweis
Wenn Sie die Hash-Funktionen adler32 oder crc32 benötigen, sind diese im Modul zlib verfügbar.
Hash-Algorithmen¶
Für jeden Hash-Typ gibt es eine Konstruktormethode mit entsprechendem Namen. Alle geben ein Hash-Objekt mit derselben einfachen Schnittstelle zurück. Zum Beispiel: Verwenden Sie sha256(), um ein SHA-256-Hash-Objekt zu erstellen. Sie können dieses Objekt nun mit bytesähnlichen Objekten (normalerweise bytes) über die Methode update speisen. Zu jedem Zeitpunkt können Sie den Digest der bisher eingespeisten Daten über die Methoden digest() oder hexdigest() abfragen.
Um Multithreading zu ermöglichen, wird die Python GIL freigegeben, während ein Hash berechnet wird, wenn dem Konstruktor oder der Methode .update auf einmal mehr als 2047 Bytes übergeben werden.
Konstruktoren für Hash-Algorithmen, die in diesem Modul immer vorhanden sind, sind sha1(), sha224(), sha256(), sha384(), sha512(), sha3_224(), sha3_256(), sha3_384(), sha3_512(), shake_128(), shake_256(), blake2b() und blake2s(). md5() ist normalerweise ebenfalls verfügbar, obwohl es fehlen oder blockiert sein könnte, wenn Sie eine seltene "FIPS-konforme" Version von Python verwenden. Diese entsprechen algorithms_guaranteed.
Zusätzliche Algorithmen können ebenfalls verfügbar sein, wenn Ihr Python-Distribution hashlib gegen eine OpenSSL-Version gelinkt wurde, die weitere Algorithmen bereitstellt. Andere sind auf allen Installationen *nicht garantiert verfügbar* und nur über new() per Namen zugänglich. Siehe algorithms_available.
Warnung
Einige Algorithmen haben bekannte Schwächen bei Hash-Kollisionen (einschließlich MD5 und SHA1). Beziehen Sie sich auf Angriffe auf kryptografische Hash-Algorithmen und den Abschnitt hashlib-siehe auch am Ende dieses Dokuments.
Hinzugefügt in Version 3.6: SHA3 (Keccak) und SHAKE-Konstruktoren sha3_224(), sha3_256(), sha3_384(), sha3_512(), shake_128(), shake_256() wurden hinzugefügt. blake2b() und blake2s() wurden hinzugefügt.
Geändert in Version 3.9: Alle hashlib-Konstruktoren akzeptieren ein nur-Schlüsselwort-Argument usedforsecurity mit dem Standardwert True. Ein falscher Wert erlaubt die Verwendung von unsicheren und blockierten Hashing-Algorithmen in eingeschränkten Umgebungen. False gibt an, dass der Hashing-Algorithmus nicht in einem Sicherheitskontext verwendet wird, z. B. als nicht-kryptografische Einweg-Kompressionsfunktion.
Geändert in Version 3.9: Hashlib verwendet nun SHA3 und SHAKE von OpenSSL, falls diese bereitgestellt werden.
Geändert in Version 3.12: Für alle MD5-, SHA1-, SHA2- oder SHA3-Algorithmen, die das verlinkte OpenSSL nicht bereitstellt, greifen wir auf eine verifizierte Implementierung aus dem HACL* Projekt zurück.
Verwendung¶
Um den Digest des Byte-Strings b"Nobody inspects the spammish repetition" zu erhalten
>>> import hashlib
>>> m = hashlib.sha256()
>>> m.update(b"Nobody inspects")
>>> m.update(b" the spammish repetition")
>>> m.digest()
b'\x03\x1e\xdd}Ae\x15\x93\xc5\xfe\\\x00o\xa5u+7\xfd\xdf\xf7\xbcN\x84:\xa6\xaf\x0c\x95\x0fK\x94\x06'
>>> m.hexdigest()
'031edd7d41651593c5fe5c006fa5752b37fddff7bc4e843aa6af0c950f4b9406'
Kompakter
>>> hashlib.sha256(b"Nobody inspects the spammish repetition").hexdigest()
'031edd7d41651593c5fe5c006fa5752b37fddff7bc4e843aa6af0c950f4b9406'
Konstruktoren¶
- hashlib.new(name, [data, ]*, usedforsecurity=True)¶
Ist ein generischer Konstruktor, der den String-Namen des gewünschten Algorithmus als erstes Argument nimmt. Er existiert auch, um Zugriff auf die oben genannten Hashes sowie auf alle anderen Algorithmen zu ermöglichen, die Ihre OpenSSL-Bibliothek möglicherweise anbietet.
Verwendung von new() mit einem Algorithmusnamen
>>> h = hashlib.new('sha256')
>>> h.update(b"Nobody inspects the spammish repetition")
>>> h.hexdigest()
'031edd7d41651593c5fe5c006fa5752b37fddff7bc4e843aa6af0c950f4b9406'
- hashlib.md5([data, ]*, usedforsecurity=True)¶
- hashlib.sha1([data, ]*, usedforsecurity=True)¶
- hashlib.sha224([data, ]*, usedforsecurity=True)¶
- hashlib.sha256([data, ]*, usedforsecurity=True)¶
- hashlib.sha384([data, ]*, usedforsecurity=True)¶
- hashlib.sha512([data, ]*, usedforsecurity=True)¶
- hashlib.sha3_224([data, ]*, usedforsecurity=True)¶
- hashlib.sha3_256([data, ]*, usedforsecurity=True)¶
- hashlib.sha3_384([data, ]*, usedforsecurity=True)¶
- hashlib.sha3_512([data, ]*, usedforsecurity=True)¶
Benannte Konstruktoren wie diese sind schneller als das Übergeben eines Algorithmusnamens an new().
Attribute¶
Hashlib stellt folgende konstante Modulattribute zur Verfügung:
- hashlib.algorithms_guaranteed¶
Ein Set, das die Namen der Hash-Algorithmen enthält, die garantiert von diesem Modul auf allen Plattformen unterstützt werden. Beachten Sie, dass 'md5' in dieser Liste enthalten ist, obwohl einige Anbieter eine seltene "FIPS-konforme" Python-Version anbieten, die es ausschließt.
Hinzugefügt in Version 3.2.
- hashlib.algorithms_available¶
Ein Set, das die Namen der Hash-Algorithmen enthält, die im laufenden Python-Interpreter verfügbar sind. Diese Namen werden erkannt, wenn sie an
new()übergeben werden.algorithms_guaranteedwird immer eine Teilmenge davon sein. Derselbe Algorithmus kann mehrmals in diesem Set unter verschiedenen Namen erscheinen (dank OpenSSL).Hinzugefügt in Version 3.2.
Hash-Objekte¶
Die folgenden Werte werden als konstante Attribute von den von den Konstruktoren zurückgegebenen Hash-Objekten bereitgestellt:
- hash.digest_size¶
Die Größe des resultierenden Hashes in Bytes.
- hash.block_size¶
Die interne Blockgröße des Hash-Algorithmus in Bytes.
Ein Hash-Objekt hat die folgenden Attribute:
- hash.name¶
Der kanonische Name dieses Hashes, immer in Kleinbuchstaben und immer als Parameter für
new()geeignet, um einen weiteren Hash dieses Typs zu erstellen.Geändert in Version 3.4: Das Namensattribut ist seit der Einführung von CPython vorhanden, war aber bis Python 3.4 nicht formell spezifiziert und existiert daher möglicherweise nicht auf einigen Plattformen.
Ein Hash-Objekt hat die folgenden Methoden:
- hash.update(data)¶
Aktualisiert das Hash-Objekt mit dem bytesähnlichen Objekt. Wiederholte Aufrufe sind äquivalent zu einem einzelnen Aufruf mit der Konkatenation aller Argumente:
m.update(a); m.update(b)ist äquivalent zum.update(a+b).
- hash.digest()¶
Gibt den Digest der bisher übergebenen Daten an die Methode
update()zurück. Dies ist ein Bytes-Objekt der Größedigest_size, das Bytes im gesamten Bereich von 0 bis 255 enthalten kann.
- hash.hexdigest()¶
Ähnlich wie
digest(), außer dass der Digest als String-Objekt doppelter Länge zurückgegeben wird, das nur Hexadezimalziffern enthält. Dies kann verwendet werden, um den Wert sicher per E-Mail oder in anderen nicht-binären Umgebungen auszutauschen.
- hash.copy()¶
Gibt eine Kopie ("Klon") des Hash-Objekts zurück. Dies kann verwendet werden, um effizient die Digests von Daten zu berechnen, die einen gemeinsamen Anfangs-Teilstring haben.
SHAKE variable length digests¶
- hashlib.shake_128([data, ]*, usedforsecurity=True)¶
- hashlib.shake_256([data, ]*, usedforsecurity=True)¶
Die Algorithmen shake_128() und shake_256() bieten variable Länge der Digests mit Länge_in_bits//2 bis zu 128 oder 256 Bit Sicherheit. Daher benötigen ihre Digest-Methoden eine Länge. Die maximale Länge ist durch den SHAKE-Algorithmus nicht begrenzt.
- shake.digest(length)¶
Gibt den Digest der bisher übergebenen Daten an die Methode
update()zurück. Dies ist ein Bytes-Objekt der Größe length, das Bytes im gesamten Bereich von 0 bis 255 enthalten kann.
- shake.hexdigest(length)¶
Ähnlich wie
digest(), außer dass der Digest als String-Objekt doppelter Länge zurückgegeben wird, das nur Hexadezimalziffern enthält. Dies kann verwendet werden, um den Wert per E-Mail oder in anderen nicht-binären Umgebungen auszutauschen.
Beispielverwendung
>>> h = hashlib.shake_256(b'Nobody inspects the spammish repetition')
>>> h.hexdigest(20)
'44709d6fcb83d92a76dcb0b668c98e1b1d3dafe7'
Dateihashing¶
Das hashlib-Modul bietet eine Hilfsfunktion für effizientes Hashing einer Datei oder eines dateiähnlichen Objekts.
- hashlib.file_digest(fileobj, digest, /)¶
Gibt ein Digest-Objekt zurück, das mit dem Inhalt des Dateiobjekts aktualisiert wurde.
fileobj muss ein dateiähnliches Objekt sein, das zum Lesen im Binärmodus geöffnet wurde. Es akzeptiert Dateiobjekte von eingebauten
open(),BytesIO-Instanzen, SocketIO-Objekten vonsocket.socket.makefile()und ähnlichen. fileobj muss im Blockierungsmodus geöffnet sein, andernfalls kann einBlockingIOErrorausgelöst werden.Die Funktion kann die Python-I/O umgehen und direkt den File-Deskriptor von
fileno()verwenden. Es ist anzunehmen, dass fileobj nach dem Rücksprung oder Auslösen der Funktion in einem unbekannten Zustand ist. Es liegt in der Verantwortung des Aufrufers, fileobj zu schließen.digest muss entweder ein Hash-Algorithmusname als str, ein Hash-Konstruktor oder ein aufrufbares Objekt sein, das ein Hash-Objekt zurückgibt.
Beispiel
>>> import io, hashlib, hmac >>> with open("library/hashlib.rst", "rb") as f: ... digest = hashlib.file_digest(f, "sha256") ... >>> digest.hexdigest() '...'
>>> buf = io.BytesIO(b"somedata") >>> mac1 = hmac.HMAC(b"key", digestmod=hashlib.sha512) >>> digest = hashlib.file_digest(buf, lambda: mac1)
>>> digest is mac1 True >>> mac2 = hmac.HMAC(b"key", b"somedata", digestmod=hashlib.sha512) >>> mac1.digest() == mac2.digest() True
Hinzugefügt in Version 3.11.
Geändert in Version 3.14: Löst nun ein
BlockingIOErroraus, wenn die Datei im Nicht-Blockierungsmodus geöffnet ist. Zuvor wurden zufällige Null-Bytes zum Digest hinzugefügt.
Schlüsselableitung¶
Schlüsselableitungs- und Key-Stretching-Algorithmen sind für sicheres Passwort-Hashing konzipiert. Naive Algorithmen wie sha1(password) sind nicht resistent gegen Brute-Force-Angriffe. Eine gute Passwort-Hashing-Funktion muss abstimmbar, langsam und mit einem Salt versehen sein.
- hashlib.pbkdf2_hmac(hash_name, password, salt, iterations, dklen=None)¶
Die Funktion bietet die PKCS#5 Password-Based Key Derivation Function 2. Sie verwendet HMAC als Pseudozufallsfunktion.
Der String hash_name ist der gewünschte Name des Hash-Digest-Algorithmus für HMAC, z.B. 'sha1' oder 'sha256'. password und salt werden als Byte-Puffer interpretiert. Anwendungen und Bibliotheken sollten password auf eine sinnvolle Länge (z.B. 1024) begrenzen. salt sollte etwa 16 oder mehr Bytes aus einer geeigneten Quelle sein, z.B.
os.urandom().Die Anzahl der iterations sollte basierend auf dem Hash-Algorithmus und der Rechenleistung gewählt werden. Ab 2022 werden Hunderttausende von Iterationen von SHA-256 empfohlen. Für die Begründung, warum und wie Sie das Beste für Ihre Anwendung auswählen, lesen Sie Anhang A.2.2 von NIST-SP-800-132. Die Antworten auf die Stackexchange-Frage zu pbkdf2-Iterationen erklären dies im Detail.
dklen ist die Länge des abgeleiteten Schlüssels in Bytes. Wenn dklen
Noneist, wird die Digest-Größe des Hash-Algorithmus hash_name verwendet, z.B. 64 für SHA-512.>>> from hashlib import pbkdf2_hmac >>> our_app_iters = 500_000 # Application specific, read above. >>> dk = pbkdf2_hmac('sha256', b'password', b'bad salt' * 2, our_app_iters) >>> dk.hex() '15530bba69924174860db778f2c6f8104d3aaf9d26241840c8c4a641c8d000a9'
Funktion nur verfügbar, wenn Python mit OpenSSL kompiliert wurde.
Hinzugefügt in Version 3.4.
Geändert in Version 3.12: Funktion ist jetzt nur noch verfügbar, wenn Python mit OpenSSL erstellt wurde. Die langsame reine Python-Implementierung wurde entfernt.
- hashlib.scrypt(password, *, salt, n, r, p, maxmem=0, dklen=64)¶
Die Funktion bietet die scrypt Password-Based Key Derivation Function gemäß RFC 7914.
password und salt müssen bytesähnliche Objekte sein. Anwendungen und Bibliotheken sollten password auf eine sinnvolle Länge (z.B. 1024) begrenzen. salt sollte etwa 16 oder mehr Bytes aus einer geeigneten Quelle sein, z.B.
os.urandom().n ist der CPU/Speicherkostenfaktor, r die Blockgröße, p der Parallelisierungsfaktor und maxmem begrenzt den Speicher (OpenSSL 1.1.0 Standard sind 32 MiB). dklen ist die Länge des abgeleiteten Schlüssels in Bytes.
Hinzugefügt in Version 3.6.
BLAKE2¶
BLAKE2 ist eine kryptografische Hash-Funktion, definiert in RFC 7693, die in zwei Varianten kommt:
BLAKE2b, optimiert für 64-Bit-Plattformen und erzeugt Digests beliebiger Größe zwischen 1 und 64 Bytes,
BLAKE2s, optimiert für 8- bis 32-Bit-Plattformen und erzeugt Digests beliebiger Größe zwischen 1 und 32 Bytes.
BLAKE2 unterstützt **keyed mode** (ein schnellerer und einfacherer Ersatz für HMAC), **salted hashing**, **personalization** und **tree hashing**.
Hash-Objekte aus diesem Modul folgen der API der Standardbibliothek hashlib.
Erstellen von Hash-Objekten¶
Neue Hash-Objekte werden durch Aufruf von Konstruktorfunktionen erstellt:
- hashlib.blake2b(data=b'', *, digest_size=64, key=b'', salt=b'', person=b'', fanout=1, depth=1, leaf_size=0, node_offset=0, node_depth=0, inner_size=0, last_node=False, usedforsecurity=True)¶
- hashlib.blake2s(data=b'', *, digest_size=32, key=b'', salt=b'', person=b'', fanout=1, depth=1, leaf_size=0, node_offset=0, node_depth=0, inner_size=0, last_node=False, usedforsecurity=True)¶
Diese Funktionen geben die entsprechenden Hash-Objekte zur Berechnung von BLAKE2b oder BLAKE2s zurück. Sie können optional diese allgemeinen Parameter übergeben
data: initialer Datenblock zum Hashen, der ein byte-ähnliches Objekt sein muss. Er kann nur als Positionsargument übergeben werden.
digest_size: Größe des Ausgabe-Digests in Bytes.
key: Schlüssel für keyed Hashing (bis zu 64 Bytes für BLAKE2b, bis zu 32 Bytes für BLAKE2s).
salt: Salt für randomisiertes Hashing (bis zu 16 Bytes für BLAKE2b, bis zu 8 Bytes für BLAKE2s).
person: Personalisierungsstring (bis zu 16 Bytes für BLAKE2b, bis zu 8 Bytes für BLAKE2s).
Die folgende Tabelle zeigt die Grenzen für allgemeine Parameter (in Bytes)
Hash |
digest_size |
len(key) |
len(salt) |
len(person) |
|---|---|---|---|---|
BLAKE2b |
64 |
64 |
16 |
16 |
BLAKE2s |
32 |
32 |
8 |
8 |
Hinweis
Die BLAKE2-Spezifikation definiert konstante Längen für Salt- und Personalisierungsparameter. Aus Bequemlichkeit akzeptiert diese Implementierung jedoch Byte-Strings beliebiger Größe bis zur angegebenen Länge. Wenn die Länge des Parameters kleiner als angegeben ist, wird er mit Nullen aufgefüllt, sodass zum Beispiel b'salt' und b'salt\x00' denselben Wert haben. (Dies gilt nicht für key.)
Diese Größen sind als Modul Konstanten verfügbar, die unten beschrieben werden.
Konstruktorfunktionen akzeptieren auch die folgenden Baum-Hashing-Parameter
fanout: Fanout (0 bis 255, 0 wenn unbegrenzt, 1 im sequenziellen Modus).
depth: maximale Tiefe des Baumes (1 bis 255, 255 wenn unbegrenzt, 1 im sequenziellen Modus).
leaf_size: maximale Byte-Länge eines Blattes (0 bis
2**32-1, 0 wenn unbegrenzt oder im sequenziellen Modus).node_offset: Knoten-Offset (0 bis
2**64-1für BLAKE2b, 0 bis2**48-1für BLAKE2s, 0 für das erste, linkeste Blatt oder im sequenziellen Modus).node_depth: Knotentiefe (0 bis 255, 0 für Blätter oder im sequenziellen Modus).
inner_size: interne Digest-Größe (0 bis 64 für BLAKE2b, 0 bis 32 für BLAKE2s, 0 im sequenziellen Modus).
last_node: boolescher Wert, der angibt, ob der verarbeitete Knoten der letzte ist (
Falsefür den sequenziellen Modus).
Siehe Abschnitt 2.10 in der BLAKE2-Spezifikation für eine umfassende Übersicht über Baum-Hashing.
Konstanten¶
- blake2b.SALT_SIZE¶
- blake2s.SALT_SIZE¶
Salt-Länge (maximale Länge, die von Konstruktoren akzeptiert wird).
- blake2b.PERSON_SIZE¶
- blake2s.PERSON_SIZE¶
Länge des Personalisierungsstrings (maximale Länge, die von Konstruktoren akzeptiert wird).
- blake2b.MAX_KEY_SIZE¶
- blake2s.MAX_KEY_SIZE¶
Maximale Schlüsselgröße.
- blake2b.MAX_DIGEST_SIZE¶
- blake2s.MAX_DIGEST_SIZE¶
Maximale Digest-Größe, die die Hash-Funktion ausgeben kann.
Beispiele¶
Einfaches Hashing¶
Um den Hash von Daten zu berechnen, sollten Sie zunächst ein Hash-Objekt erstellen, indem Sie die entsprechende Konstruktorfunktion (blake2b() oder blake2s()) aufrufen, es dann mit den Daten aktualisieren, indem Sie update() auf dem Objekt aufrufen, und schließlich den Digest aus dem Objekt erhalten, indem Sie digest() (oder hexdigest() für eine hex-kodierte Zeichenkette) aufrufen.
>>> from hashlib import blake2b
>>> h = blake2b()
>>> h.update(b'Hello world')
>>> h.hexdigest()
'6ff843ba685842aa82031d3f53c48b66326df7639a63d128974c5c14f31a0f33343a8c65551134ed1ae0f2b0dd2bb495dc81039e3eeb0aa1bb0388bbeac29183'
Als Abkürzung können Sie den ersten Datenblock zum Aktualisieren direkt an den Konstruktor als Positionsargument übergeben
>>> from hashlib import blake2b
>>> blake2b(b'Hello world').hexdigest()
'6ff843ba685842aa82031d3f53c48b66326df7639a63d128974c5c14f31a0f33343a8c65551134ed1ae0f2b0dd2bb495dc81039e3eeb0aa1bb0388bbeac29183'
Sie können hash.update() beliebig oft aufrufen, um den Hash iterativ zu aktualisieren
>>> from hashlib import blake2b
>>> items = [b'Hello', b' ', b'world']
>>> h = blake2b()
>>> for item in items:
... h.update(item)
...
>>> h.hexdigest()
'6ff843ba685842aa82031d3f53c48b66326df7639a63d128974c5c14f31a0f33343a8c65551134ed1ae0f2b0dd2bb495dc81039e3eeb0aa1bb0388bbeac29183'
Verwendung unterschiedlicher Digest-Größen¶
BLAKE2 verfügt über konfigurierbare Digest-Größen bis zu 64 Bytes für BLAKE2b und bis zu 32 Bytes für BLAKE2s. Um beispielsweise SHA-1 durch BLAKE2b zu ersetzen, ohne die Größe der Ausgabe zu ändern, können wir BLAKE2b anweisen, 20-Byte-Digests zu erzeugen
>>> from hashlib import blake2b
>>> h = blake2b(digest_size=20)
>>> h.update(b'Replacing SHA1 with the more secure function')
>>> h.hexdigest()
'd24f26cf8de66472d58d4e1b1774b4c9158b1f4c'
>>> h.digest_size
20
>>> len(h.digest())
20
Hash-Objekte mit unterschiedlichen Digest-Größen haben völlig unterschiedliche Ausgaben (kürzere Hashes sind *keine* Präfixe von längeren Hashes); BLAKE2b und BLAKE2s erzeugen unterschiedliche Ausgaben, auch wenn die Ausgabelänge gleich ist
>>> from hashlib import blake2b, blake2s
>>> blake2b(digest_size=10).hexdigest()
'6fa1d8fcfd719046d762'
>>> blake2b(digest_size=11).hexdigest()
'eb6ec15daf9546254f0809'
>>> blake2s(digest_size=10).hexdigest()
'1bf21a98c78a1c376ae9'
>>> blake2s(digest_size=11).hexdigest()
'567004bf96e4a25773ebf4'
Keyed Hashing¶
Keyed Hashing kann zur Authentifizierung als schnellerer und einfacherer Ersatz für Hash-based message authentication code (HMAC) verwendet werden. BLAKE2 kann dank der von BLAKE geerbten Indifferenzierbarkeitseigenschaft sicher im Prefix-MAC-Modus verwendet werden.
Dieses Beispiel zeigt, wie ein (hex-kodierter) 128-Bit-Authentifizierungscode für die Nachricht b'message data' mit dem Schlüssel b'pseudorandom key' erhalten wird
>>> from hashlib import blake2b
>>> h = blake2b(key=b'pseudorandom key', digest_size=16)
>>> h.update(b'message data')
>>> h.hexdigest()
'3d363ff7401e02026f4a4687d4863ced'
Als praktisches Beispiel kann eine Webanwendung Cookies, die an Benutzer gesendet werden, symmetrisch signieren und sie später verifizieren, um sicherzustellen, dass sie nicht manipuliert wurden
>>> from hashlib import blake2b
>>> from hmac import compare_digest
>>>
>>> SECRET_KEY = b'pseudorandomly generated server secret key'
>>> AUTH_SIZE = 16
>>>
>>> def sign(cookie):
... h = blake2b(digest_size=AUTH_SIZE, key=SECRET_KEY)
... h.update(cookie)
... return h.hexdigest().encode('utf-8')
>>>
>>> def verify(cookie, sig):
... good_sig = sign(cookie)
... return compare_digest(good_sig, sig)
>>>
>>> cookie = b'user-alice'
>>> sig = sign(cookie)
>>> print("{0},{1}".format(cookie.decode('utf-8'), sig))
user-alice,b'43b3c982cf697e0c5ab22172d1ca7421'
>>> verify(cookie, sig)
True
>>> verify(b'user-bob', sig)
False
>>> verify(cookie, b'0102030405060708090a0b0c0d0e0f00')
False
Obwohl es einen nativen keyed Hashing-Modus gibt, kann BLAKE2 natürlich auch in HMAC-Konstruktionen mit dem hmac-Modul verwendet werden
>>> import hmac, hashlib
>>> m = hmac.new(b'secret key', digestmod=hashlib.blake2s)
>>> m.update(b'message')
>>> m.hexdigest()
'e3c8102868d28b5ff85fc35dda07329970d1a01e273c37481326fe0c861c8142'
Randomisiertes Hashing¶
Durch Setzen des Parameters salt können Benutzer dem Hash-Algorithmus Randomisierung hinzufügen. Randomisiertes Hashing ist nützlich zum Schutz vor Kollisionsangriffen auf den Hash-Algorithmus, der in digitalen Signaturen verwendet wird.
Randomisiertes Hashing ist für Situationen konzipiert, in denen eine Partei, der Nachrichtenersteller, die gesamte Nachricht oder Teile davon generiert, die von einer zweiten Partei, dem Signierer, signiert werden soll. Wenn der Nachrichtenersteller in der Lage ist, Kollisionen von kryptografischen Hash-Algorithmen zu finden (d.h. zwei Nachrichten, die denselben Hash-Wert ergeben), kann er sinnvolle Versionen der Nachricht vorbereiten, die denselben Hash-Wert und dieselbe digitale Signatur, aber unterschiedliche Ergebnisse ergeben würden (z. B. Überweisung von 1.000.000 $ auf ein Konto statt 10 $). Kryptografische Hash-Algorithmen wurden mit Kollisionsresistenz als Hauptziel entwickelt, aber die aktuelle Konzentration auf Angriffe auf kryptografische Hash-Algorithmen kann dazu führen, dass ein bestimmter kryptografischer Hash-Algorithmus weniger Kollisionsresistenz bietet als erwartet. Randomisiertes Hashing bietet dem Signierer zusätzlichen Schutz, indem es die Wahrscheinlichkeit reduziert, dass ein Ersteller zwei oder mehr Nachrichten generieren kann, die während des Prozesses der digitalen Signaturerzeugung letztendlich denselben Hash-Wert ergeben - selbst wenn es praktisch ist, Kollisionen für den Hash-Algorithmus zu finden. Die Verwendung von randomisiertem Hashing kann jedoch die Sicherheit einer digitalen Signatur verringern, wenn alle Teile der Nachricht vom Signierer vorbereitet werden.
(NIST SP-800-106 „Randomized Hashing for Digital Signatures“)
In BLAKE2 wird der Salt als einmalige Eingabe für den Hash-Algorithmus während der Initialisierung verarbeitet, anstatt als Eingabe für jede Kompressionsfunktion.
Warnung
Salted Hashing (oder einfach Hashing) mit BLAKE2 oder einem anderen universellen kryptografischen Hash-Algorithmus wie SHA-256 ist nicht für das Hashing von Passwörtern geeignet. Siehe BLAKE2 FAQ für weitere Informationen.
>>> import os
>>> from hashlib import blake2b
>>> msg = b'some message'
>>> # Calculate the first hash with a random salt.
>>> salt1 = os.urandom(blake2b.SALT_SIZE)
>>> h1 = blake2b(salt=salt1)
>>> h1.update(msg)
>>> # Calculate the second hash with a different random salt.
>>> salt2 = os.urandom(blake2b.SALT_SIZE)
>>> h2 = blake2b(salt=salt2)
>>> h2.update(msg)
>>> # The digests are different.
>>> h1.digest() != h2.digest()
True
Personalisierung¶
Manchmal ist es nützlich, den Hash-Algorithmus zu zwingen, für denselben Eingabe unterschiedliche Digests für verschiedene Zwecke zu erzeugen. Zitiert die Autoren des Skein-Hash-Algorithmus
Wir empfehlen allen Anwendungsdesignern, dies ernsthaft in Betracht zu ziehen. Wir haben viele Protokolle gesehen, bei denen ein Hash, der in einem Teil des Protokolls berechnet wird, in einem völlig anderen Teil verwendet werden kann, da zwei Hash-Berechnungen auf ähnlichen oder verwandten Daten durchgeführt wurden und der Angreifer die Anwendung zwingen kann, die Hash-Eingaben gleich zu machen. Die Personalisierung jedes im Protokoll verwendeten Hash-Algorithmus verhindert summarisch diese Art von Angriff.
(The Skein Hash Function Family, S. 21)
BLAKE2 kann personalisiert werden, indem Bytes an das Argument person übergeben werden
>>> from hashlib import blake2b
>>> FILES_HASH_PERSON = b'MyApp Files Hash'
>>> BLOCK_HASH_PERSON = b'MyApp Block Hash'
>>> h = blake2b(digest_size=32, person=FILES_HASH_PERSON)
>>> h.update(b'the same content')
>>> h.hexdigest()
'20d9cd024d4fb086aae819a1432dd2466de12947831b75c5a30cf2676095d3b4'
>>> h = blake2b(digest_size=32, person=BLOCK_HASH_PERSON)
>>> h.update(b'the same content')
>>> h.hexdigest()
'cf68fb5761b9c44e7878bfb2c4c9aea52264a80b75005e65619778de59f383a3'
Personalisierung zusammen mit dem keyed Modus kann auch verwendet werden, um unterschiedliche Schlüssel aus einem einzigen abzuleiten.
>>> from hashlib import blake2s
>>> from base64 import b64decode, b64encode
>>> orig_key = b64decode(b'Rm5EPJai72qcK3RGBpW3vPNfZy5OZothY+kHY6h21KM=')
>>> enc_key = blake2s(key=orig_key, person=b'kEncrypt').digest()
>>> mac_key = blake2s(key=orig_key, person=b'kMAC').digest()
>>> print(b64encode(enc_key).decode('utf-8'))
rbPb15S/Z9t+agffno5wuhB77VbRi6F9Iv2qIxU7WHw=
>>> print(b64encode(mac_key).decode('utf-8'))
G9GtHFE1YluXY1zWPlYk1e/nWfu0WSEb0KRcjhDeP/o=
Baum-Modus¶
Hier ist ein Beispiel für das Hashing eines minimalen Baumes mit zwei Blattknoten
10
/ \
00 01
Dieses Beispiel verwendet 64-Byte interne Digests und gibt den 32-Byte finalen Digest zurück
>>> from hashlib import blake2b
>>>
>>> FANOUT = 2
>>> DEPTH = 2
>>> LEAF_SIZE = 4096
>>> INNER_SIZE = 64
>>>
>>> buf = bytearray(6000)
>>>
>>> # Left leaf
... h00 = blake2b(buf[0:LEAF_SIZE], fanout=FANOUT, depth=DEPTH,
... leaf_size=LEAF_SIZE, inner_size=INNER_SIZE,
... node_offset=0, node_depth=0, last_node=False)
>>> # Right leaf
... h01 = blake2b(buf[LEAF_SIZE:], fanout=FANOUT, depth=DEPTH,
... leaf_size=LEAF_SIZE, inner_size=INNER_SIZE,
... node_offset=1, node_depth=0, last_node=True)
>>> # Root node
... h10 = blake2b(digest_size=32, fanout=FANOUT, depth=DEPTH,
... leaf_size=LEAF_SIZE, inner_size=INNER_SIZE,
... node_offset=0, node_depth=1, last_node=True)
>>> h10.update(h00.digest())
>>> h10.update(h01.digest())
>>> h10.hexdigest()
'3ad2a9b37c6070e374c7a8c508fe20ca86b6ed54e286e93a0318e95e881db5aa'
Danksagungen¶
BLAKE2 wurde von Jean-Philippe Aumasson, Samuel Neves, Zooko Wilcox-O’Hearn und Christian Winnerlein entworfen, basierend auf dem SHA-3-Finalisten BLAKE, erstellt von Jean-Philippe Aumasson, Luca Henzen, Willi Meier und Raphael C.-W. Phan.
Er verwendet den Kernalgorithmus aus dem ChaCha-Cipher, entworfen von Daniel J. Bernstein.
Die stdlib-Implementierung basiert auf dem Modul pyblake2. Sie wurde von Dmitry Chestnykh basierend auf einer C-Implementierung von Samuel Neves geschrieben. Die Dokumentation wurde aus pyblake2 kopiert und von Dmitry Chestnykh geschrieben.
Der C-Code wurde teilweise von Christian Heimes für Python umgeschrieben.
Die folgende Public Domain Widmung gilt sowohl für die C-Hash-Funktionsimplementierung, den Erweiterungscode als auch für diese Dokumentation
Soweit nach dem Gesetz möglich, haben die/der Autor(en) alle Urheberrechte und verwandten und nachbarrechtlichen Rechte an dieser Software weltweit dem öffentlichen Bereich gewidmet. Diese Software wird ohne jegliche Gewährleistung vertrieben.
Sie sollten eine Kopie der CC0 Public Domain Widmung zusammen mit dieser Software erhalten haben. Wenn nicht, siehe https://creativecommons.org/publicdomain/zero/1.0/.
Die folgenden Personen haben bei der Entwicklung geholfen oder ihre Änderungen gemäß der Creative Commons Public Domain Dedication 1.0 Universal dem Projekt und dem öffentlichen Bereich beigesteuert
Alexandr Sokolovskiy
Siehe auch
- Modul
hmac Ein Modul zur Generierung von Nachrichtenauthentifizierungscodes mithilfe von Hashes.
- Modul
base64 Eine weitere Möglichkeit, binäre Hashes für nicht-binäre Umgebungen zu kodieren.
- https://nvlpubs.nist.gov/nistpubs/fips/nist.fips.180-4.pdf
Die FIPS 180-4 Veröffentlichung zu Secure Hash Algorithms.
- https://csrc.nist.gov/pubs/fips/202/final
Die FIPS 202 Veröffentlichung zum SHA-3 Standard.
- https://www.blake2.net/
Offizielle BLAKE2-Website.
- https://en.wikipedia.org/wiki/Cryptographic_hash_function
Wikipedia-Artikel mit Informationen darüber, welche Algorithmen bekannte Probleme haben und was dies für ihre Verwendung bedeutet.
- https://www.ietf.org/rfc/rfc8018.txt
PKCS #5: Password-Based Cryptography Specification Version 2.1
- https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-132.pdf
NIST-Empfehlung für die schlüsselbasierte Ableitung von Passwörtern.