Python >> Python Program >  >> Python

Har bcrypt en maximal lösenordslängd?

Ja, bcrypt har en maximal lösenordslängd. Den ursprungliga artikeln innehåller detta:

nyckelargumentet är en hemlig krypteringsnyckel, som kan vara ett användarvalt lösenord på upp till 56 byte (inklusive en avslutande nollbyte när nyckeln är en ASCII-sträng).

Så man skulle kunna sluta sig till en maximal inmatningslösenordslängd på 55 tecken (den avslutande nollan räknas inte med). ASCII-tecken, märk väl:ett generiskt Unicode-tecken, när det är kodat i UTF-8, kan använda upp till fyra bytes; och det visuella konceptet för en glyph kan bestå av ett obegränsat antal Unicode-tecken. Du kommer att spara många bekymmer om du begränsar dina lösenord till vanlig ASCII.

Det råder dock en betydande förvirring om den faktiska gränsen. Vissa människor tror att gränsen för "56 byte" inkluderar ett 4-byte salt, vilket leder till en nedre gräns på 51 tecken. Andra människor påpekar att algoritmen internt hanterar saker som 18 32-bitars ord, för totalt 72 byte, så du kan gå till 71 tecken (eller till och med 72 om du inte hanterar strängar med en avslutande nolla).

Faktiska implementeringar kommer att ha en gräns som beror på vad implementeraren trodde och verkställde i allt ovanstående. Alla anständiga implementeringar tillåter dig minst 50 tecken. Utöver det garanteras inte support. Om du behöver stödja lösenord som är längre än 50 tecken, kan du lägga till ett preliminärt hash-steg, som diskuterats i denna fråga (men, naturligtvis, betyder detta att du inte längre beräknar "the" bcrypt, utan en lokal variant, så interoperabilitet går ner i avloppet).

Redigera: det har påpekats för mig att även om artikeln ur en kryptografs synvinkel är den ultimata referensen, det är inte nödvändigtvis så designerna tänkte kring det. Den "ursprungliga" implementeringen kunde bearbeta upp till 72 byte. Beroende på din inställning till formalism kan du hävda att implementeringen är rätt och artikeln är fel. Hur som helst, sådant är det nuvarande tillståndet att mitt råd förblir giltigt:om du håller under 50 tecken kommer du att klara dig överallt. (Självklart hade det varit bättre om algoritmen inte hade en längdbegränsning i första hand.)


tl;lr:BCrypt är begränsad till 72 byte, inte 56.

Bakgrund

BCrypt är begränsat till 72 byte. I originaldokumentet nämns också användningen av en nollterminator. Det betyder att du i allmänhet skulle begränsa till:

  • 71 tecken + 1 byte null terminator

Men revisionen av BCrypt 2a specificerar användningen av UTF-8-kodning (medan den ursprungliga whitepapern hänvisar till ASCII). När du använder UTF-8 betyder ett tecken inte en byte, t.ex.:

  • Noël är fyra tecken, men fem byte (N o e ¨ l )
  • är ett tecken, men fyra byte (F0 9F 92 A9 )
  • M̡̢̛̖̗̘̙̜̝̞̟̠̀́̂̃̄̅̆̇̉̊̋̌̍̎̏̐̑̒̓̔̕̚ är ett tecken, men 74 byte (med nollterminatorn inkluderad)

Så detta kastar en skiftnyckel i hur många "tecken" du får lov.

Var kommer 55 eller 56 ifrån då?

Den ursprungliga whitepaper nämner en maximal nyckellängd på 56 byte:

Slutligen är nyckelargumentet en hemlig krypteringsnyckel, som kan vara ett användarvalt lösenord på upp till 56 byte (inklusive en avslutande nollbyte när nyckeln är en ASCII-sträng).

Detta var ett missförstånd baserat på Blowfishs maximala rekommenderade nyckelstorlek på 448 bitar. (448 / 8 =56 byte). Blowfish-krypteringsalgoritmen, som bcrypt härrör från, har en maximal nyckelstorlek på 448 bitar. Från Bruce Schneiers originaltidning från 1993 Beskrivning av en ny nyckel med variabel längd, 64-bitars blockchiffer (Blowfish) :

Blockstorleken är 64 bitar och nyckeln kan vara valfri längd upp till 448 bitar.

Å andra sidan kan bcrypt-algoritmen (och gör det) stödja upp till 72 byte för nyckeln, t.ex.:

  • 71×8-bitars tecken + 1× 8-bitars nollterminator

Gränsen på 72 byte kommer från storleken Blowfish P-Box, som är 18 DWORDs (18×4 byte =72 byte). Från den ursprungliga bcrypt-vitboken:

Blowfish är ett 64-bitars blockchiffer, strukturerat som ett 16-runda Feistel-nätverk [14]. Den använder 18 32-bitars undernycklar , P1, ..., P18, som den härleder från krypteringsnyckeln. Undernycklarna kallas gemensamt för P-arrayen

Den kanoniska OpenBSD-implementeringen kommer att trunkera alla nycklar som överstiger 72 byte.

Det betyder att om din UTF8-sträng som överstiger 72 byte kommer den att trunkeras till 72 byte.

Varning :

  • denna trunkering tar bort nollterminatorn
  • denna trunkering sker till och med mitt i tecken (för ett tecken med flera kodpunkter)

Till exempel, om dina lösenord slutar med:

"...häftapparat"

UTF-8-kodningen för BCrypt kommer att vara:

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

Detta innebär att i den kanoniska OpenBSD-implementeringen skärs byten av i mitten av ett tecken (även om det lämnar en ogiltig utf-8 bytesekvens):

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

Bli av med maximal längd

Under de senaste åren har det uppmärksammats som en bra idé att en hashningsalgoritm för lösenord inte bör ha någon maxgräns. Men det finns ett problem med att tillåta en klient att använda en obegränsad lösenord:

  • det introducerar en överbelastningsattack av någon som skickar in ett lösenord på flera gigabyte.

Det är därför det nu börjar bli vanligt att pre-hash en användares lösenord med något som SHA2-256. Den resulterande bas-64-kodade strängen, t.ex.:

n4bQgYhMfWWaL+qgxVrQFaO/TxsrC4Is0V1sFbDwCgg=

kommer aldrig att bestå av 44 ASCII-tecken (45 med nollterminatorn).

Detta är tillvägagångssättet från DropBox och ingår i bcrypt.net:

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

Detta innebär att din dyra hashalgoritm kommer inte att orsaka ett överbelastningsskydd.


Ja, BCrypt har en övre gräns på 72 tecken. Det är en begränsning av själva Blowfish-chifferet. Ett sätt att komma runt det är att först använda SHA-256 och sedan BCryptera resultatet. I ditt fall skulle det vara något liknande

hashpw(sha256('pass'), salt)