PHP crypt () taglia il sale come sarebbe troppo lungo

10

Sto usando Blowfish con PHP crypt () per l'hashing delle password ma ho notato qualcosa di strano. Citando la documentazione PHP:

CRYPT_BLOWFISH - Blowfish hashing with a salt as follows: "$2a$", "$2x$" or "$2y$", a two digit cost parameter, "$", and 22 digits from the alphabet "./0-9A-Za-z".

Ho notato che il sale che viene incluso nell'hash finale è di 1 carattere breve (l'ultimo è tagliato) come se il sale fosse troppo lungo, ma non è così.

Esempio di output di script:

Salt: 97504ebb48c4619f820f83 with length 22

Blowfish: $2a$13$97504ebb48c4619f820f8u4QTtlV5MoqHt9l7hmK4jEohUXrI.0PK

Hash match.

Come puoi vedere, il sale casuale ha esattamente 22 cifre, ma il '3' manca nell'hash finale. Se faccio il sal solo 21 caratteri ottengo un hash corrotto e non funziona. Quindi, perché taglia l'ultimo carattere?

Gli esempi sul manuale PHP aggiungono anche un $ finale al sale casuale. È $ lì per una ragione o lo hanno semplicemente aggiunto in modo casuale a Blowfish, SHA-256 e SHA-512 per confondere tutti?

E infine, questo è il mio codice:

if (CRYPT_BLOWFISH == 1) {
    $salt = md5(uniqid(rand(), TRUE));
    $salt = substr($salt, 0, 22);

    echo "Salt: " . $salt . " with length " . strlen($salt) . "<br />";
    $pass = "rasmuslerdorf";

    $bsalt = "$2a$13$".$salt;
    $blowfish=crypt($pass, $bsalt);
    echo 'Blowfish:     ' . $blowfish . "<br />";

    if (crypt($pass, $blowfish) == $blowfish) {
        echo "Hash match.<br />";
    }
    else echo "no<br />";
}
else {
    exit("You need php 5.3 or newer");
}
    
posta cen 30.09.2012 - 15:48
fonte

1 risposta

18

In realtà il '3' è lì, ma è chiamato 'u'.

Spiegazioni: bcrypt ha bisogno di un sale a 128 bit. Il sale che fornisci dovrebbe essere in "base64 modificato", cioè costituito da lettere, cifre, "/" o "." segni (questo è "modificato" perché in vero Base64 , viene usato il segno "+" invece di ".", e l'ordine è diverso). Dato che questo è un alfabeto di 64 elementi, ogni carattere vale 6 bit e i tuoi 22 caratteri codificano 132 bit.

Bcrypt utilizza solo i primi 128 bit dei tuoi 132 bit, quindi gli ultimi quattro bit vengono completamente ignorati. Gli ultimi quattro bit sono gli ultimi quattro bit dell'ultimo carattere salt. Nella base64 modificata, 'u' ha valore 48, 110000 in binario, mentre '3' ha valore 57, 111001 in binario. Come puoi vedere, i due valori differiscono solo nell'ultimo (più a destra) quattro bit, che vengono ignorati.

Quello che succede è che l'implementazione di bcrypt che usi per prima cosa converte il tuo sale (22 caratteri) in un buffer a 128-bit (16 byte), ed è qui che si verifica il rilascio. Quindi il codice lo convertirà indietro in base64 modificato, ma questa volta utilizzerà zeri per i "quattro bit mancanti", trasformando così il tuo '3' in una 'u'. Se si utilizza '97504ebb48c4619f820f8u' invece di '97504ebb48c4619f820f83' come sale, si otterrà lo stesso identico output di bcrypt, poiché questi due sali differiscono solo negli ultimi quattro bit, che vengono ignorati.

    
risposta data 30.09.2012 - 16:25
fonte

Leggi altre domande sui tag