Per comprendere questo problema, devi prima capire perché abbiamo hash delle password. È completamente possibile memorizzare una password in testo normale su un server e confrontare semplicemente la password trasmessa con la password ricevuta. Finché la password è protetta durante il transito, questo è un mezzo di autenticazione sicuro (segreto condiviso).
Il motivo per cui le password vengono sottoposte ad hashing è perché il problema non è l'autenticazione, ma l'archiviazione. Se il server venisse compromesso, l'attaccante avrebbe immediatamente accesso a tutti gli account utente poiché ora conoscerebbe il segreto utilizzato per l'autenticazione degli utenti.
L'hashing funge da barriera a questo. Poiché il server non conosce l'effettivo input richiesto per l'autenticazione, anche una compromissione del DB non garantisce a un utente malintenzionato l'accesso agli account utente. Avrebbero comunque bisogno di capire l'input da fornire per raggiungere i valori hash confrontati con l'applicazione. Sicuramente potrebbero alterare tutti i valori in qualcosa che conoscono, ma questo solleverebbe rapidamente sospetti e il sistema verrebbe spento e protetto.
Quindi, il problema con l'hashing lato client è che rende effettivamente risultato dell'hash la password anziché la password. Non c'è nulla che impedisca a un utente malintenzionato di aggirare il client ufficiale e di inviare semplicemente l'hash finito direttamente al server. Non fornisce ulteriore (o perdita) di sicurezza durante l'autenticazione, ma nella situazione in cui l'hashing è progettato per proteggersi, non offre nulla poiché l'hash memorizzato nel DB è in realtà il segreto condiviso trasmesso al server.
Detto questo, ci sono due cose importanti che l'hashing lato client ti offre. Sebbene non aiuti affatto a proteggere il tuo sistema, può aiutare a proteggere il tuo utente. Se stai trasmettendo la password in modo insicuro o la trasmissione viene compromessa senza che il codice client venga compromesso, proteggerai comunque la password dell'utente (che potrebbe riutilizzare su altri siti) dalla fuga di notizie.
L'altro è che puoi fornire iterazioni aggiuntive di un hash per rendere più difficile un attacco offline contro il DB senza dover utilizzare i cicli del server (estendendo anche la lunghezza della "password intermedia che il client invia"), ma hai ancora bisogno di cicli server sufficienti per proteggere la password allungata da un client non autorizzato. Anche in questo caso, la protezione primaria che questo offre è impedire che la password originale venga scoperta ma non fa nulla per aiutare a proteggere il meccanismo di autenticazione del tuo sito.
In altre parole, fornisce alcune protezioni minori, dal punto di vista del server, l'hash lato client dovrebbe essere trattato come se fosse la password diretta dell'utente. Non fornisce né maggiore né minore sicurezza sul server rispetto a se l'utente avesse fornito direttamente la propria password e dovesse essere protetto come tale.
Se tu voglio essere in grado di fornire quel livello extra di sicurezza, consiglierei due hash. Hash una volta lato client per creare una nuova password univoca, quindi hash quella password sul server per creare un valore memorizzato nel DB. In questo modo ottieni il meglio da entrambi i mondi.
Per la maggior parte, SSL è sufficientemente affidabile per proteggere lo scambio che l'hash iniziale prima della trasmissione è visto come non necessario e un server compromesso potrebbe sempre alterare il codice inviato al client in modo tale che l'hash iniziale non venga eseguito. Semplicemente non è un'alternativa efficace a SSL e non offre un vantaggio aggiuntivo sufficiente per valerne i costi e la complessità.