Bcrypt

bcrypt-Hash erzeugen oder ein Passwort dagegen prüfen, ohne den Browser zu verlassen: Kosten und Variante $2a$, $2b$ oder $2y$ wählen und jeden Hash zerlegen.

Nichts, was Sie hier eingeben, verlässt diesen Browser. Die Arbeit läuft in einem Web Worker in diesem Tab — öffnen Sie Ihr eigenes Netzwerkpanel und sehen Sie zu: Während der Berechnung geht keine einzige Anfrage hinaus.

Hash erzeugen

Ein Passwort, Kosten und eine Variante. Das Salt wird bei jedem Lauf frisch aus diesem Browser gezogen, dasselbe Passwort ergibt also jedes Mal einen anderen Hash — so gehört sich bcrypt, das ist kein Fehler.

Passwort gegen einen Hash prüfen

Ein eingefügter Hash wird sofort zerlegt, ohne Passwort und ohne Wartezeit. Mit dem Passwort kommt die Antwort auf die Übereinstimmung. Ein Hash lässt sich nicht umkehren, hier so wenig wie sonst wo.

Was in einem bcrypt-Hash wirklich steckt

Ein bcrypt-Hash ist eine einzige Zeichenkette aus sechzig Zeichen, und jeder ihrer Teile liegt offen. Nichts daran ist geheim außer dem Passwort, das sie hervorgebracht hat — und das steckt gar nicht darin. Sie auseinanderzunehmen braucht keinen Schlüssel, kein Passwort und keine Rechenzeit: Diese Seite tut es in dem Moment, in dem Sie einen Hash einfügen.

  • Die Variante, das Feld, mit dem die Zeichenkette beginnt: $2b$, $2a$ oder $2y$. Sie benennt, nach wessen Regeln der Hash entstanden ist.
  • Die Kosten, geschrieben als genau zwei Ziffern: 04 bis 31. Sie sind ein Exponent, also bedeuten Kosten von 12 genau 2^12 — 4.096 — Runden Schlüsselstreckung, und Kosten von 13 sind die doppelte Arbeit von 12 und nicht ein Dreizehntel mehr.
  • Das Salt, zweiundzwanzig Zeichen: sechzehn zufällige Bytes, offen neben der Antwort abgelegt, die sie gesalzen haben.
  • Der Digest, die letzten einunddreißig Zeichen: dreiundzwanzig Bytes Ausgabe. Das ist der einzige Teil, der vom Passwort abhängt, und er ist nicht der Hash — der Hash ist die ganze Zeichenkette.

Das Alphabet, aus dem diese Zeichen stammen, ist bcrypts eigenes und nicht das Standard-Base64: Es läuft ./A-Za-z0-9, ein Punkt und ein Schrägstrich eröffnen es also dort, wo Base64 Plus und Schrägstrich ans Ende stellt. Ein gewöhnlicher Base64-Dekodierer gibt daraus falsche Bytes zurück statt eines Fehlers — ein klassischer Weg, einen Nachmittag zu verlieren.

Die Grenze von zweiundsiebzig Bytes wird in Bytes gezählt, und das macht einen Unterschied

bcrypt liest höchstens zweiundsiebzig Bytes eines Passworts und beachtet nichts, was danach kommt. Nicht zweiundsiebzig Zeichen — zweiundsiebzig Bytes UTF-8, und wie viele Zeichen das sind, hängt davon ab, was die Buchstaben einer Sprache kosten: die sechsundzwanzig lateinischen Grundbuchstaben kosten je ein Byte, jeder andere kostet mehr. Im Deutschen ist der Unterschied klein und trotzdem echt: jedes ä, ö, ü und ß kostet zwei Bytes, ein Passwort mit ein paar solchen Buchstaben erreicht die Grenze also einige Zeichen vor den zweiundsiebzig. Eines, das nur aus ihnen besteht, erreichte sie bei sechsunddreißig.

  • ASCII kostet ein Byte je Zeichen, wer Englisch spricht, trifft die Grenze also bei zweiundsiebzig Zeichen und fast nie.
  • Hebräisch, Arabisch, Russisch und Griechisch kosten zwei Bytes je Buchstabe, die Grenze kommt dort also bei sechsunddreißig Zeichen.
  • Japanisch, Koreanisch und Chinesisch kosten drei, sie kommt dort also bei vierundzwanzig.
  • Die meisten Emoji kosten vier, und viele von denen, die Menschen wirklich tippen, sind mehrere zusammengefügte Codepunkte — eine Handvoll davon ist schon das ganze Budget.

Der Byte-Zähler unter dem Passwortfeld ist dafür da, dass Sie das kommen sehen, statt es hinterher zu entdecken. Und der Schnitt fällt aufs Byte und nicht aufs Zeichen, genau wie es jede Referenzimplementierung macht — ein Mehrbyte-Zeichen, das auf der Grenze sitzt, verliert also einen Teil von sich und behält den Rest. Das ist das kompatible Verhalten und kein Fehler, und diese Seite sagt es, wenn es passiert.

Und nun der Teil, der alles Übrige erklärt: Das Abschneiden ist in der Antwort unsichtbar. Die Schlüsselexpansion mischt genau zweiundsiebzig Bytes des Schlüssels in ihren Zustand und läuft bei einem längeren nie um, also ergeben ein hundert Byte langes Passwort und seine ersten zweiundsiebzig Bytes denselben Digest. Es gibt nichts, was eine Implementierung erkennen, und nichts, was sie melden könnte — deshalb wirft keine Bibliothek einen Fehler, und deshalb passen zwei verschiedene lange Passwörter, die in ihren ersten zweiundsiebzig Bytes übereinstimmen, beide zu demselben gespeicherten Hash. Auch diese Seite kann ein langes Passwort nicht ablehnen — wenn Sie es gegen einen Hash prüfen, den ein echtes System durch Abschneiden erzeugt hat, brauchen Sie die Antwort —, also gibt sie die Antwort und sagt Ihnen, was abgeschnitten wurde.

Die Variante ändert das Präfix und nicht den Digest

Die Variante sieht aus wie eine Versionsnummer und ist keine. Die drei, die dieses Werkzeug schreibt, sind nicht geordnet, keine löst eine andere ab, und die Wahl zwischen ihnen ist eine Frage der Kompatibilität und keine der Sicherheit.

  • $2b$ ist das, worauf OpenBSD sich festgelegt hat und was Python, Node und Go heute ausgeben. Hier ist es die Vorgabe und die richtige Antwort, solange nichts eine andere erzwingt.
  • $2a$ ist die ältere, und manche langlebigen Java- und Spring-Security-Installationen erwarten sie noch immer.
  • $2y$ ist das, was PHPs password_hash und damit Laravel schreiben; ein Hash, der in jene Welt eingefügt wird, will meistens diese.

Was die drei trennt, ist ihr Umgang mit einem Schlüssel von mehr als 255 Bytes, und bcrypt hat bei zweiundsiebzig längst aufgehört zu lesen — kein Passwort, das Sie hier eingeben können, reicht also an diesen Unterschied heran. Für alles, was dieses Werkzeug je bekommen wird, ergeben alle drei dieselben dreiundzwanzig Bytes und unterscheiden sich nur in den vier Zeichen am Anfang. Wechseln Sie die Variante, und der Digest bleibt, wo er ist.

Zwei weitere gibt es, und dieses Werkzeug benennt sie, statt sie zu berechnen. $2x$ ist keine Korrektur: Openwall hat sie geprägt, um einen Vorzeichenerweiterungsfehler absichtlich nachzubilden, damit Hashes aus dem kaputten Code weiter prüfbar blieben — sie hier umzusetzen hieße, einen bekannten Defekt in das Werkzeug selbst zu holen. $2$ ist die ursprüngliche, aus der Zeit vor dem abschließenden Nullbyte im Schlüssel. Keine von beiden wird heute noch von irgendetwas geschrieben; wenn Sie eine in der Hand halten, kommt sie aus einem System, das so alt ist, dass die Variante Ihre geringste Entdeckung ist.

Die Kosten, und was sie auf Ihrer eigenen Maschine kosten

Die Kosten sind der Arbeitsfaktor, von 4 bis 31, und sie sind ein Exponent: Jede Stufe verdoppelt die Zeit. Genau darum geht es bei bcrypt. Ein Passwort-Hash soll langsam sein, denn ein Angreifer mit einer gestohlenen Tabelle zahlt denselben Preis bei jedem Rateversuch, und eine Verdopplung der Kosten halbiert die Zahl der Versuche pro Sekunde, die er für sein Geld bekommt.

Was bestimmte Kosten tatsächlich brauchen, ist eine Tatsache über die Maschine, die sie ausführt, und keine Zahl, die sich vorher aufschreiben ließe: Ein Telefon und ein Server liegen zwei Größenordnungen auseinander. Deshalb misst diese Seite, statt zu zitieren: Sie lässt beim Laden einen kurzen Hash auf Ihrem eigenen Gerät laufen und rechnet von dort hoch — weshalb die Schätzung neben dem Kostenregler einen Moment leer ist und dann erscheint. Oberhalb einiger Sekunden fragt sie, bevor sie beginnt, damit eine vertippte Ziffer nicht wie eine eingefrorene Seite aussieht.

Zur Wahl einer Zahl: 12 ist das, was Laravel und das bcrypt-Paket für Python standardmäßig ausgeben, und heute eine vernünftige Untergrenze für den Produktivbetrieb. Niedrigere Kosten sind für Test-Fixtures gedacht, wo eine Testsuite, die fünfzig Benutzer anlegt, nicht eine Sekunde pro Benutzer verbrauchen sollte. Kosten oberhalb von etwa 15 sollten Sie gegen Ihren echten Anmeldeverkehr messen, bevor Sie sie ausliefern, denn jede Anmeldung zahlt den Preis mit.

# Apache: eine htpasswd-Zeile mit Kosten 12 schreiben
htpasswd -nbBC 12 alice "correct horse battery staple"

# PHP und Laravel: password_hash gibt $2y$ aus
php -r 'echo password_hash("correct horse battery staple", PASSWORD_BCRYPT);'

# Python: das bcrypt-Paket gibt $2b$ aus, und gensalt nimmt die Kosten
python -c "import bcrypt; print(bcrypt.hashpw(b'correct horse battery staple', bcrypt.gensalt(12)))"

Das Salt, und wann ein hier erzeugter Hash nichts zum Speichern ist

Das Salt sind sechzehn zufällige Bytes, die für jeden Hash frisch gezogen werden, und es liegt offen in der Zeichenkette selbst. Es ist kein Geheimnis und war nie als eines gedacht: Seine Aufgabe ist, dass zwei gleiche Passwörter zwei völlig unverwandte Hashes ergeben, damit eine gestohlene Tabelle nicht mit einem einzigen vorberechneten Wörterbuch angegriffen werden kann.

Auch deshalb gibt Ihnen dasselbe Passwort hier bei jedem Druck auf den Knopf einen anderen Hash. Das ist kein Fehler, und die alte Antwort ist nicht veraltet: Ein frisches Salt ist bcrypt bei der Arbeit. Jeder dieser Hashes passt zum Passwort, weil das Salt in der Zeichenkette mitreist, die geprüft wird.

Das Salt-Feld unter den erweiterten Einstellungen gibt es für eine einzige Aufgabe: den Hash eines anderen exakt nachzubauen, damit sich zwei Implementierungen gegenüberstellen lassen. Fügen Sie einen ganzen Hash hinein, und Kosten und Variante richten sich automatisch danach, sodass das richtige Passwort die Eingabe Zeichen für Zeichen reproduziert. Was so entsteht, dient dem Vergleich und nicht der Speicherung: Ein zweimal verwendetes Salt ist ein Salt, das seine Aufgabe aufgegeben hat.

Ein bcrypt-Hash lässt sich nicht umkehren

Auf Seiten wie diese kommen Menschen, weil sie einen bcrypt-Hash entschlüsseln wollen. Das geht nicht, und der Grund ist nicht, dass es schwer wäre: Das Passwort steht nicht in der Zeichenkette. Sechzig Zeichen tragen eine Variante, Kosten, sechzehn zufällige Bytes und dreiundzwanzig Bytes Ausgabe, und keine Anordnung davon enthält ein Passwort irgendeiner Länge. Es wurde nichts verschlüsselt, also gibt es nichts zu entschlüsseln.

Was eine Website tun kann — und was die tun, die mit Entschlüsselung werben — ist raten. Man nimmt eine Liste häufiger Passwörter, hasht jedes davon gegen Ihr Salt und mit Ihren Kosten und sieht nach, ob eines passt. bcrypt ist darauf ausgelegt, genau das teuer zu machen, dafür sind die Kosten da, und dieses Werkzeug bietet es in keiner Form an.

Die ehrliche Fassung dieser Frage ist meist eine andere, und die hat eine Antwort: Was steckt in dieser Zeichenkette, und ergibt dieses eine Passwort sie? Beides steht auf dieser Seite. Fügen Sie den Hash ein, um alles zu sehen, was er trägt, und ergänzen Sie ein Passwort für ein Ja oder ein Nein.

Häufig gestellte Fragen

Wird mein Passwort an einen Server geschickt?
Nein. Alles geschieht in diesem Browser-Tab — das Hashen läuft in einem Web Worker auf Ihrer eigenen Maschine, das Passwort landet nie in der Adresse, und in den Browserspeicher wird nichts geschrieben. Öffnen Sie Ihr Netzwerkpanel, tippen Sie ein Passwort und drücken Sie den Knopf: Es geht keine einzige Anfrage hinaus. Das ist der Unterschied zwischen dieser Seite und den beiden Websites, die bei derselben Frage über ihr stehen.
Lässt sich ein bcrypt-Hash zurück in das Passwort entschlüsseln?
Nein, und nicht, weil es schwer wäre. Das Passwort steht nicht in der Zeichenkette: Darin stehen eine Variante, Kosten, ein Salt und dreiundzwanzig Bytes Ausgabe, und nichts davon enthält die Eingabe. Wer anbietet, einen zu entschlüsseln, rät häufige Passwörter gegen Ihr Salt — genau das, was bcrypt eigens langsam machen soll.
Warum ergibt dasselbe Passwort jedes Mal einen anderen Hash?
Weil für jeden Lauf ein neues zufälliges Salt gezogen wird und das Salt Teil der Zeichenkette ist. Jeder dieser Hashes passt zu demselben Passwort — der Prüfer liest das Salt aus dem Hash, den Sie einfügen, und muss deshalb nicht wissen, welcher Lauf ihn erzeugt hat.
Mein Passwort wurde bei zweiundsiebzig Bytes abgeschnitten. Warum kam kein Fehler?
Weil es nichts zu erkennen gibt. bcrypt mischt genau zweiundsiebzig Bytes des Schlüssels in seinen Zustand und liest nie weiter, also ergeben ein langes Passwort und seine ersten zweiundsiebzig Bytes denselben Digest — das Abschneiden hinterlässt keine Spur, die eine Bibliothek bemerken könnte. Diese Seite sagt Ihnen, dass es passiert ist, und das ist das Meiste, was eine Implementierung ehrlich tun kann.
Warum hat mein Passwort die Grenze schon bei sechsunddreißig Zeichen erreicht?
Weil die Grenze zweiundsiebzig Bytes und nicht zweiundsiebzig Zeichen sind und hebräische, arabische, russische und griechische Buchstaben in UTF-8 je zwei Bytes kosten. Japanische, koreanische und chinesische kosten drei, dort kommt die Grenze also bei vierundzwanzig Zeichen, und die meisten Emoji kosten vier. Im Deutschen kosten ä, ö, ü und ß ebenfalls zwei Bytes: Ein Passwort, das nur aus ihnen besteht, wird bei sechsunddreißig abgeschnitten. Der Zähler unter dem Feld zeigt die Bytes schon beim Tippen.
Welche Variante soll ich wählen?
Die, die das System erwartet, in das Sie einfügen: $2y$ für PHP und Laravel, $2a$ für älteres Spring Security, $2b$ überall sonst. Das ist eine Frage der Kompatibilität und keine der Sicherheit — bei jeder Länge, die dieses Werkzeug bekommen kann, ergeben alle drei denselben Digest und unterscheiden sich nur in diesen vier Zeichen am Anfang.
Welche Kosten soll ich verwenden?
12 ist die verbreitete Vorgabe und eine vernünftige Untergrenze für den Produktivbetrieb. Nehmen Sie niedrige Kosten für Test-Fixtures, damit Ihre Suite die Schlüsselstreckung nicht fünfzigmal bezahlt, und messen Sie alles oberhalb von 15 zuerst gegen Ihren echten Anmeldeverkehr, denn jede erfolgreiche Anmeldung zahlt denselben Preis wie ein Angreifer.
Kann ein hier erzeugter Hash bedenkenlos in eine echte Benutzertabelle?
Zum Befüllen einer Datenbank, für eine Fixture oder eine htpasswd-Zeile: ja — das Salt stammt aus der kryptografischen Zufallsquelle Ihres Browsers. Aber dies ist eine Seite zum Ausprobieren und kein Dienst für Anmeldedaten: Geben Sie das Salt selbst ein, hört das Ergebnis auf, sicher speicherbar zu sein, was die Seite auch gleich sagt, und ein Passwort, das Schutz verdient, wird besser dort geprägt, wo es leben soll.
Warum beginnt mein Hash mit $2y$, obwohl der Code, der ihn erzeugt hat, bcrypt sagt?
Weil PHPs password_hash $2y$ schreibt und Laravel darauf aufbaut. Es ist derselbe Algorithmus wie $2b$; die Variante hält fest, welche Implementierung die Zeichenkette geschrieben hat. Ein Prüfer, der sie ablehnt, lehnt die Variante ab und scheitert nicht daran, das Passwort abzugleichen.
Ich habe einen Hash eingefügt, und er sagt, das Salt sei anders geschrieben. Ist er kaputt?
Nein. Zweiundzwanzig Zeichen können mehr Bits kodieren, als sechzehn Bytes brauchen, also fallen vier Bits am Ende weg, und manche Salts haben mehr als eine Schreibweise, die zu denselben Bytes dekodiert. Echte Systeme haben solche ausgegeben, deshalb liest diese Seite einen solchen Hash, statt ihn abzulehnen, und nennt Ihnen die kanonische Schreibweise.

Verwandte Werkzeuge