Qualsiasi motivo per cui non dovrei fare salatura e hashing prima di passare a bCrypt?

1

Ho letto sull'archiviazione delle password e così via, e sono giunto alla conclusione che ho bisogno di usare bCrypt. Ho un'implementazione che funziona correttamente, ma mi sto chiedendo quale sia il modo migliore per andare avanti con la mia applicazione.

Il precedente sistema di memorizzazione delle password era semplicemente hashing e salatura. In realtà è più facile per me mantenere questo sistema e stratificare bCrypt in alto piuttosto che riscriverlo con bCrypt da solo.

Tuttavia, continuo a leggere che la combinazione di algoritmi di hashing diversi è una cattiva idea - quindi volevo ottenere qualche chiarimento, poiché non posso pensare ad alcun motivo per non implementare in questo modo:

  • Hash (password + sale + pepe) * 1000 iterazioni - SHA-256
  • L'hash risultante viene eseguito tramite bCrypt con la sua salatura e un fattore di lavoro definito.
  • Hash finale memorizzato nel DB insieme al sale originale
  • Per controllare la password, è riutilizzato come sopra prima di essere sottoposto al controllo hash di bScrypt.

C'è qualche ragione per cui non dovrei fare le cose in questo modo e dovrei abbandonare la password originale + salt + pepper in favore di dare semplicemente la semplice password per bCrypt?

Grazie

    
posta Gary 21.05.2014 - 17:46
fonte

1 risposta

3

Non ci sono evidenti punti deboli di sicurezza con i tuoi schemi. Quello originale (a parte il non memorizzare un numero di versione con gli hash in modo da poter aggiornare il tuo schema a più giri o un nuovo pepe, se necessario), o il nuovo a strati con bcrypt. Bcrypt può prendere 72 byte di input quindi non ci sono problemi nell'usare sha256 come hash.

Sarei attento se codificherai l'output del tuo shash6shsh rafforzato dalle chiavi prima di inviarlo a bcrypt. In linea di principio, probabilmente è meglio tenerlo in forma binaria - se si stesse usando sha512, sarebbe possibile utilizzare tutti i byte (come 72 byte = 576 bit). Garantito con sha-256, non importa finché lo fai correttamente. Un hash sha256 è lungo 32 byte (in binario con lettere non stampabili), lungo 44 byte dopo la codifica base64, lungo 64 byte (in esadecimale), ma 88 byte se si codifica in base64 l'hash con codifica esadecimale (che sarebbe parzialmente sicurezza troncata e leggermente indebolita - ad esempio, anziché 256 bit di sicurezza intrinseca hai 72/88 * 256 ~ 209 bit).

Nota, se un utente ha una password di entropia estremamente alta (ad esempio, 400 bit di entropia) che in linea di principio richiederebbe ~ 2 ^ 400 di tempo per craccare, usando sha256 come fase intermedia ci vorrà solo del tempo ~ 2 ^ 256 prima che sia probabile trovare una password che funzioni. Concesso 2 ^ 256 è completamente sicuro in questi giorni (come qualcosa di significativamente più di ~ 2 ^ 80, quindi questa differenza non ha rilevanza pratica).

Diventa più complicato e potenzialmente più fastidioso da mantenere (garantito che si potrebbe sostenere che questa è una buona cosa - se il database è mai stato trapelato sarebbe più difficile per un utente malintenzionato fare in modo che una GPU la forza bruta). Se aggiorni il tuo sistema e le cose non funzionano perfettamente, ci sono molti più punti in cui le cose potrebbero andare storte. Se qualcuno nuovo sviluppatore arriva e vede gli hash in forma come bcrypt, può presumere che siano solo bcrypt e cambi qualcosa che infrange il sistema.

Un'alternativa sarebbe quella di mantenere entrambi i sistemi sul posto e di aggiornare con garbo gli utenti a bcrypt sul loro prossimo login riuscito.

def login(username, password):
    user = get_user(username)
    if user.uses_old_hash():
        calculated_old_hash = sha256_1000_round(password, salt=user.salt)
        if constant_time_string_compare(user.hash, calculated_old_hash):
            calculated_new_hash = bcrypt.hashpw(password, salt=bcrypt.gensalt(12))
            user.hash = calculated_new_hash
            print "Login Successful"
            return True
        else:
            print "Login Failed"
            return False
    else:
        hash = user.hash
        calculated_new_hash = bcrypt.hashpw(password, salt=hash)
        if constant_time_string_compare(hash, calculated_new_hash):
            print "Login Successful"
            return True
        else:
            print "Login Failed"
            return False
    
risposta data 21.05.2014 - 18:38
fonte

Leggi altre domande sui tag