it-swarm.dev

Bcrypt ha una lunghezza massima della password?

Oggi stavo scherzando con bcrypt e ho notato qualcosa:

hashpw('testtdsdddddddddddddddddddddddddddddddddddddddddddddddsddddddddddddddddd', salt)
Output: '$2a$15$jQYbLa5m0PIo7eZ6MGCzr.BC17WEAHyTHiwv8oLvyYcg3guP5Zc1y'

hashpw('testtdsdddddddddddddddddddddddddddddddddddddddddddddddsdddddddddddddddddd', salt)
Output: '$2a$15$jQYbLa5m0PIo7eZ6MGCzr.BC17WEAHyTHiwv8oLvyYcg3guP5Zc1y'

Bcrypt ha una lunghezza massima della password?

91
d0ctor

Sì, bcrypt ha una lunghezza massima della password. Il articolo originale contiene questo:

l'argomento chiave è una chiave di crittografia segreta, che può essere una password scelta dall'utente fino a 56 byte (incluso un byte zero di terminazione quando la chiave è una ASCII).

Quindi si potrebbe dedurre una lunghezza massima della password di input di 55 caratteri (senza contare lo zero finale). ASCII caratteri, attenzione: un carattere Unicode generico, se codificato in UTF-8, può usare fino a quattro byte; e il concetto visivo di a glifo può consistere in un numero illimitato di caratteri Unicode. Risparmierete molte preoccupazioni se limitate le vostre password alla semplice ASCII.

Tuttavia, vi è una notevole confusione sul limite effettivo. Alcune persone credono che il limite di "56 byte" includa un salt di 4 byte, portando ad un limite inferiore di 51 caratteri. Altre persone sottolineano che l'algoritmo, internamente, gestisce le cose come 18 parole a 32 bit, per un totale di 72 byte, quindi potresti andare a 71 caratteri (o anche 72 se non gestisci le stringhe con uno zero finale).

Actual implementations avrà un limite che dipende da ciò che l'implementatore ha creduto e applicato in tutto quanto sopra. Tutte le implementazioni decenti ti permetteranno almeno 50 caratteri. Oltre a ciò, il supporto non è garantito. Se devi supportare password più lunghe di 50 caratteri, puoi aggiungere un passaggio preliminare di hashing, come discusso in questa domanda (ma, ovviamente, ciò significa che non devi più calcolare "il" bcrypt, ma una variante locale, quindi l'interoperabilità va giù per lo scarico).

Modifica: mi è stato fatto notare che sebbene, dal punto di vista di un crittografo, il articolo sia il ultimo riferimento, questo non è necessariamente il modo in cui i designer ci hanno pensato. L'implementazione "originale" potrebbe elaborare fino a 72 byte. A seconda della tua posizione sul formalismo, potresti affermare che l'implementazione è corretta e l'articolo è sbagliato. Ad ogni modo, questo è lo stato attuale delle cose che il mio consiglio rimane valido: se mantieni meno di 50 caratteri, starai bene ovunque. (Ovviamente sarebbe stato meglio se l'algoritmo non avesse avuto un limite di lunghezza in primo luogo.)

76
Tom Leek

tl; lr: BCrypt è limitato a 72 byte, non a 56.

Sfondo

BCrypt è limitato a 72 byte. L'articolo originale menziona anche l'uso di un terminatore null. Ciò significa che generalmente ti limiteresti a:

  • 71 caratteri + 1 byte null terminator

Ma la revisione BCrypt 2a specifica l'uso della codifica UTF-8 (mentre il white paper originale si riferisce ad ASCII). Quando si utilizza UTF-8, un carattere non significa un byte, ad es .:

  • Noël ha quattro caratteri, ma cinque byte (Noe¨l)
  • ???? è un carattere, ma quattro byte (F09F92A9)
  • M̡̢̛̖̗̘̙̜̝̞̟̠̀́̂̃̄̅̆̇̉̊̋̌̍̎̏̐̑̒̓̔̕̚ è un carattere, ma 74 byte (con il terminatore null incluso)

Quindi questo lancia una chiave inglese in quanti caratteri sei autorizzato.

Da dove vengono allora 55 o 56?

Il white paper originale menziona una lunghezza massima della chiave di 56 byte:

Infine, l'argomento chiave è una chiave di crittografia segreta, che può essere una password scelta dall'utente fino a 56 byte (incluso un byte zero di terminazione quando la chiave è una ASCII).

Questo è stato un malinteso basato sulla dimensione della chiave massima consigliata di Blowfish di 448 bit. (448/8 = 56 byte). L'algoritmo di crittografia Blowfish, da cui deriva bcrypt, ha una dimensione massima della chiave di 448 bit. Dall'articolo originale di Bruce Schneier del 1993 Descrizione di una nuova chiave a lunghezza variabile, cifratura a blocchi a 64 bit (Blowfish) :

La dimensione del blocco è di 64 bit e la chiave può essere di qualsiasi lunghezza fino a 448 bit.

D'altra parte, l'algoritmo bcrypt può (e fa) supportare fino a 72 byte per la chiave, ad es .:

  • 71 caratteri a 8 bit + terminatore null

Il limite di 72 byte deriva dalla dimensione della P-Box Blowfish, che è 18 DWORD (18 * 4 byte = 72 byte). Dal white paper originale di bcrypt:

Blowfish è un codice a blocchi di 64 bit, strutturato come una rete Feistel a 16 round [14]. Utilizza 18 sottochiavi a 32 bit , P1, ..., P18, che deriva dalla chiave di crittografia. Le sottochiavi sono conosciute collettivamente come P-Array

L'implementazione canonica di OpenBSD troncherà qualsiasi chiave che superi i 72 byte.

Ciò significa che se la tua stringa UTF8 supera i 72 byte, verrà troncata a 72 byte.

Attenzione :

  • questo troncamento rimuoverà il terminatore null
  • questo troncamento avverrà anche a metà carattere (per un carattere punto multi-codice)

Ad esempio, se le tue password terminano "pinzatrice ????", la codifica UTF-8 per BCrypt sarà:

    ══╤══╤═══╤═══╤═══╤═══╤═══╤═════╤═════╤═════╗        
... 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

Nell'implementazione canonica di OpenBSD, i byte sono tagliati nel mezzo di un carattere (anche se ti lascia una sequenza di utf-8 byte non valida):

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

Sbarazzarsi della massima lunghezza

Negli ultimi anni, è stata riconosciuta una buona idea che un algoritmo di hashing delle password non dovrebbe avere limiti massimi. Ma c'è un problema nel consentire a un client di usare una password illimitata :

  • introduce un attacco denial of service da parte di qualcuno che invia una password multi-gigabyte.

Questo è il motivo per cui ora sta diventando comune a pre-hash la password di un utente con qualcosa come SHA2-256. La stringa codificata base 64 risultante, ad es .:

n4bQgYhMfWWaL + qgxVrQFaO/TxsrC4Is0V1sFbDwCgg =

sarà sempre e solo 44 ASCII (45 con terminatore null).

Questo è l'approccio adottato da DropBox ed è incluso in bcrypt.net :

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

Ciò significa che il tuo algoritmo di hashing costoso non ti causerà una negazione del servizio.

21
Ian Boyd

Sì, BCrypt ha un limite massimo di 72 caratteri. È una limitazione del codice Blowfish stesso. Un modo per aggirare il problema è usare prima SHA-256 e poi BCrypt il risultato. Nel tuo caso sarebbe qualcosa di simile

hashpw(sha256('pass'), salt)
17
Adi