In primo luogo, la "migliore pratica" è quella di cessare di usare il termine "crittografia" perché SHA-256 non è crittografia . Questo è chiamato hashing . Se i tuoi sviluppatori senior e gli auditor di terze parti parlano tutti di SHA-256 come "crittografia", allora stai sicuro che nessuno di loro sa veramente di cosa stanno parlando.
Nel tuo sistema, qualunque sia il client che invia, sia esso "crittografato" (con hash) o non sul client, è un valore che garantisce l'accesso; quel valore è quindi equivalente alla password e rivelarlo è altrettanto pericoloso per la sicurezza del tuo server come password in chiaro. Questo tipo di hashing sul lato client non porta il miglioramento della sicurezza che i vostri auditor sembrano ritenerlo fare. Ad aggravare la situazione è il fatto che quando il client esegue l'hashing con il codice Javascript, quel codice Javascript è stato appena inviato dal server stesso , quindi un server compromesso potrebbe inviare perfettamente qualche Javascript che semplicemente riceve la password dell'utente come lo digita e invia quella password a un server in Mongolia.
In ogni caso, le menti umane sono quelle che sono, le password memorizzate dall'utente sono deboli contro la forza bruta (chiamate "attacchi di dizionario"). Una semplice invocazione di una funzione di hash crittografica come SHA-256, indipendentemente da come sia protetta crittograficamente quella funzione, è troppo veloce per fornire molta protezione qui; un PC desktop disponibile in commercio può avere hash potenziali password con un conteggio di miliardi al secondo. L'hashing della buona password richiede funzioni dedicate con un costo computazionale configurabile (ma intrinsecamente elevato). Non sarai in grado di farlo correttamente in Javascript perché Javascript è debole per le attività ad alta intensità di calcolo.
La best practice è utilizzare SSL (sempre), trasmettere la password così com'è nel tunnel SSL e lasciare che il server applichi una corretta funzione di hashing della password, cioè bcrypt (con un conteggio di iterazione abbastanza alto - il più alto che si possa tollerare dato l'hardware disponibile e il carico di picco previsto).
Occasionalmente, si incontrano auditor in mancanza di qualcosa da dire, e potrebbe essere necessario eseguire alcune danze rituali per placarli. Una di queste danze è la spruzzatura della crittografia in vari luoghi, come la glassa per torte. Questo è un idiota ma innocuo, purché tu non rimuova le parti importanti. Nel tuo caso, puoi eseguire l'hashing SHA-256 sul lato client, ma non devi rimuovere l'hashing della password corretto sul lato server, cioè considerare il risultato dell'hash calcolato dal client come "password" e utilizzarlo come input per bcrypt. (Attenzione che le uscite hash sono binari , non testo, quindi è necessaria una certa codifica, es. Esadecimale o Base64 ).
L'extra SHA-256 sarebbe quindi inutile, ma non renderà il tuo sistema più debole, contrariamente a quello che stai cercando di fare:
So for our future release, we've transitioned to using cryptojs to encrypt passwords (unsalted) client-side, and these values are stored directly into the database without any further manipulation.
Se lo fai, allora il contenuto del database può essere usato per concedere l'accesso immediato al server. Un semplice sguardo di sola lettura al database (ad esempio un disco rigido rotto scartato, un nastro di backup perso, un attacco di SQL injection ...) e la tua sicurezza è andata in malora.