Skip to content

Gibt es für bcrypt eine maximale Passwortlänge?

Dieses Problem kann auf verschiedene Arten gelöst werden, aber wir zeigen Ihnen die für uns umfassendste Lösung.

Lösung:

Ja, bcrypt hat eine maximale Passwortlänge. Der Originalartikel enthält dies:

Das Schlüsselargument ist ein geheimer Verschlüsselungsschlüssel, der ein vom Benutzer gewähltes Passwort von bis zu 56 Bytes sein kann (einschließlich eines abschließenden Null-Bytes, wenn der Schlüssel eine ASCII-Zeichenkette ist).

Daraus lässt sich eine maximale Länge des eingegebenen Kennworts von 55 Zeichen ableiten (die abschließende Null nicht mitgerechnet). ASCII-Zeichen, wohlgemerkt: Ein allgemeines Unicode-Zeichen kann, wenn es in UTF-8 kodiert ist, bis zu vier Bytes verwenden; und das visuelle Konzept eines Glyphe kann aus einer unbeschränkten Anzahl von Unicode-Zeichen bestehen. Sie ersparen sich eine Menge Ärger, wenn Sie Ihre Passwörter auf reines ASCII beschränken.

Über die tatsächliche Grenze herrscht jedoch große Verwirrung. Einige Leute glauben, dass die "56 Bytes"-Grenze ein 4-Byte-Salz enthält, was zu einer unteren Grenze von 51 Zeichen führt. Andere weisen darauf hin, dass der Algorithmus intern 18 32-Bit-Wörter verwaltet, was insgesamt 72 Byte ergibt, so dass man auf 71 Zeichen kommen könnte (oder sogar 72, wenn man Strings nicht mit einer abschließenden Null verwaltet).

Tatsächliche Implementierungen haben eine Begrenzung, die davon abhängt, was der Implementierer geglaubt und in allen oben genannten Fällen durchgesetzt hat. Alle anständigen Implementierungen lassen mindestens 50 Zeichen zu. Darüber hinaus ist die Unterstützung nicht garantiert. Wenn Sie Passwörter mit mehr als 50 Zeichen unterstützen müssen, können Sie einen vorbereitenden Hashing-Schritt hinzufügen, wie in dieser Frage diskutiert (aber das bedeutet natürlich, dass Sie nicht mehr "das" bcrypt berechnen, sondern eine lokale Variante, so dass die Interoperabilität den Bach runtergeht).

Edit: Ich bin darauf hingewiesen worden, dass, obwohl aus Sicht eines Kryptographen, die Artikel die ultimative Referenz ist, dies aber nicht unbedingt den Vorstellungen der Entwickler entspricht. Die "ursprüngliche" Implementierung konnte bis zu 72 Bytes verarbeiten. Je nachdem, wie Sie zum Formalismus stehen, können Sie behaupten, dass die Implementierung richtig und der Artikel falsch ist. Wie dem auch sei, nach dem derzeitigen Stand der Dinge bleibt mein Rat gültig: Wenn Sie unter 50 Zeichen bleiben, werden Sie überall gut zurechtkommen. (Natürlich wäre es besser gewesen, wenn der Algorithmus von vornherein keine Längenbeschränkung gehabt hätte.)

tl;lr: BCrypt ist auf 72 Bytes begrenzt, nicht auf 56.

Hintergrund

BCrypt ist auf 72 Bytes begrenzt. Im Originalpapier wird auch die Verwendung eines Nullterminators erwähnt. Dies bedeutet, dass Sie in der Regel beschränkt auf:

  • 71 Zeichen + 1 Byte Nullterminator

Die Revision von BCrypt 2a sieht jedoch die Verwendung der UTF-8-Kodierung vor (während sich das ursprüngliche Whitepaper auf ASCII bezieht). Bei der Verwendung von UTF-8 ist ein Zeichen nicht gleichbedeutend mit einem Byte, z.B.:

  • Noël besteht aus vier Zeichen, aber fünf Bytes (Noe¨l)
  • ist ein Zeichen, aber vier Bytes (F09F92A9)
  • M̡̢̛̖̗̘̙̜̝̞̟̠̀́̂̃̄̅̆̇̉̊̋̌̍̎̏̐̑̒̓̔̕̚ ist ein Zeichen, aber 74 Bytes (mit dem Nullterminator)

Daraus ergibt sich die Frage, wie viele "Zeichen" dir erlaubt sind.

Woher kommt dann die 55 oder 56?

Im Original-Whitepaper wird eine maximale Schlüssellänge von 56 Bytes erwähnt:

Schließlich ist das Schlüsselargument ein geheimer Verschlüsselungsschlüssel, der ein vom Benutzer gewähltes Kennwort von bis zu 56 Byte sein kann (einschließlich eines abschließenden Null-Bytes, wenn der Schlüssel eine ASCII-Zeichenkette ist).

Dies war ein Missverständnis aufgrund der empfohlenen maximalen Schlüsselgröße von Blowfish 448 Bits. (448 / 8 = 56 Bytes). Der Blowfish-Verschlüsselungsalgorithmus, von dem bcrypt abgeleitet ist, hat eine maximale Schlüsselgröße von 448 Bit. Aus dem Originalbeitrag von Bruce Schneier von 1993 Beschreibung einer neuen 64-Bit-Blockchiffre mit variabler Schlüssellänge (Blowfish):

Die Blockgröße beträgt 64 Bit, und der Schlüssel kann eine beliebige Länge bis zu 448 Bit haben.

Andererseits kann der bcrypt-Algorithmus (und tut es auch) bis zu 72 Bytes für den Schlüssel unterstützen, z. B:

  • 71×8-Bit-Zeichen + 1× 8-Bit-Nullterminator

Die 72-Byte-Grenze ergibt sich aus der Größe der Blowfish-P-Box, die 18 DWORDs (18×4 Bytes = 72 Bytes) beträgt. Aus dem ursprünglichen bcrypt-Whitepaper:

Blowfish ist eine 64-Bit-Blockchiffre, die als 16-Runden-Feistel-Netzwerk aufgebaut ist. [14]. Es verwendet 18 32-Bit-Unterschlüssel, P1, ..., P18, die er aus dem Chiffrierschlüssel ableitet. Die Unterschlüssel werden zusammenfassend als P-Array

Die kanonische OpenBSD-Implementierung schneidet jeden Schlüssel ab, der 72 Bytes überschreitet.

Das bedeutet, dass dein UTF8-String, der 72 Bytes überschreitet, auf 72 Bytes gekürzt wird.

Warnung:

  • Bei dieser Abschneidung wird der Nullterminator entfernt.
  • diese Trunkierung erfolgt sogar mitten im Zeichen (bei einem Zeichen mit mehreren Codepunkten)

Wenn Ihre Passwörter zum Beispiel enden mit:

"...Hefter"

wird die UTF-8-Kodierung für BCrypt sein:

    ══╤══╤═══╤═══╤═══╤═══╤═══╤═════╤═════╤═════╗        
... 63│64│ 65│ 66│ 67│ 68│ 69│ 70  │ 71  │ 72  ║ 73   74
    s │ t│ a │ p │ l │ e │ r │ 0xF0│ 0x9F│ 0x92║ 0xA9 
    ══╧══╧═══╧═══╧═══╧═══╧═══╧═════╧═════╧═════╝
                                               |
                                            cutoff

Das bedeutet, dass in der kanonischen OpenBSD-Implementierung die Bytes abgeschnitten werden innerhalb der Mitte eines Zeichens abgeschnitten werden (auch wenn dadurch eine ungültige utf-8-Bytefolge entsteht):

    ══╤══╤═══╤═══╤═══╤═══╤═══╤═════╤═════╤═════╗
... 63│64│ 65│ 66│ 67│ 68│ 69│ 70  │ 71  │ 72  ║
    s │ t│ a │ p │ l │ e │ r │ 0xF0│ 0x9F│ 0x92║
    ══╧══╧═══╧═══╧═══╧═══╧═══╧═════╧═════╧═════╝

Abschaffung der maximalen Länge

In den letzten Jahren hat man erkannt, dass es eine gute Idee ist, dass ein Passwort-Hashing-Algorithmus keine Obergrenze haben sollte. Aber es gibt ein Problem, wenn man einem Client erlaubt, eine unbegrenzt Passwort zu verwenden:

  • führt zu einem Denial-of-Service-Angriff, wenn jemand ein Multi-Gigabyte-Passwort eingibt.

Aus diesem Grund ist es jetzt üblich, dass Pre-Hash eines Benutzerkennworts mit einem Verfahren wie SHA2-256. Die resultierende base-64 kodierte Zeichenkette, z.B.:

n4bQgYhMfWWaL+qgxVrQFaO/TxsrC4Is0V1sFbDwCgg=

werden immer nur 44 ASCII-Zeichen sein (45 mit dem Nullterminator).

Dies ist der Ansatz von DropBox und ist in bcrypt.net enthalten:

BCrypt.EnhancedHashPassword("correct battery horse staple Noël  M̡̢̛̖̗̘̙̜̝̞̟̠̀́̂̃̄̅̆̇̉̊̋̌̍̎̏̐̑̒̓̔̕̚");

Dies bedeutet, dass Ihre teure Hash-Algorithmus keinen Denial-of-Service verursachen wird.

Ja, BCrypt hat eine Obergrenze von 72 Zeichen. Das ist eine Beschränkung durch die Blowfish-Chiffre selbst. Eine Möglichkeit, dies zu umgehen, besteht darin, zuerst SHA-256 zu verwenden und dann das Ergebnis mit BCrypt zu verschlüsseln. In Ihrem Fall würde das etwa so aussehen

hashpw(sha256('pass'), salt)



Nutzen Sie unsere Suchmaschine

Suche
Generic filters

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.