Hashing lato client
Secondly assuming that the connection is compromised because of an MiTM attack. The process of how the leaked hash of the password is created is still unknown because the salt and iterations (based on the pincode) are unknown.
In caso di attacco MitM (reso possibile da un uso errato di TLS) il lato client di hashing non ti aiuterà. L'utente malintenzionato potrebbe semplicemente modificare il codice JavaScript inviato al client in modo che invii la password e il PIN in testo non crittografato. Non avendo l'utente letto e verificato il codice JavaScript completo ad ogni accesso, non c'è modo di proteggere la tua password se un utente malintenzionato interrompe il TLS.
Utilizzo di un PIN che è "mai archiviato"
I think the combination of salting and stretching locally based on a pin-code that is never stored but just known by the user makes it harder to guess the salt and also to reproduce the exact process without the user since the local used salt and amount of stretching will be unknown to the server.
Se ti capisco correttamente, il tuo obiettivo è rendere più difficile realizzare un attacco di forza bruta offline sugli hash delle password, utilizzando un salt che non viene mai memorizzato.
Consentitemi di ricapitolare i punti principali del vostro schema per stabilire una terminologia. Abbiamo una funzione di hash: HASH(data, salt, itteration count)
. L'utente ha segreti P1
(password) e P2
(PIN). P2
è hashed localmente con N
itterations e usando P2
come salt: H1 = HASH(P1, P2, N)
. H2
è inviato al server, dove è stato nuovamente sottoposto a hashing (con un valore specifico per utente salato e M
): H2 = HASH(H1, salt, M)
.
Quindi, in che modo un aggressore in carica di H2
brute forza questo? Avrebbe semplicemente usato un normale attacco di dizionario, scorrendo tra le combinazioni possibili di P1
e P2
. Per prima cosa ricreerà il processo sul client per ottenere H1
e poi ricreerà il processo sul server per ottenere H2
e confrontarlo con il valore effettivo per verificare se ha picchettato i segreti giusti.
Ciò richiederebbe N + M
itterazioni per tentativo e lei dovrebbe rendere X ^ (LENGTH(P1) + LENGTH(P2))
(dove X
è la dimensione dell'alfabeto) tenta di provare tutti i possibili segreti.
Ora confronta questo con uno schema in cui ci sarebbe solo una password con la lunghezza combinata di P1
e P2
, che è solo hash sul server con N + M
itterazioni. Il tuo schema sarebbe migliore di questo? No, sarebbe esattamente lo stesso. Ciò richiederebbe anche N + M
itterazioni per tentativo e X ^ (LENGTH(P1) + LENGTH(P2))
tentativi in totale.
Per farla breve, il tuo schema non è migliore della sola password più lunga. L'unica differenza è che hai diviso la password in due parti, un po 'complicato, e fatto un po' di hashing sul client.
O in termini più generali: non è possibile aumentare la sicurezza facendo qualcosa con il lato client della password. Se fai F(P)
e invii quello invece di P
, l'attaccante farà anche F(P)
quando forza bruta e non hai ottenuto nulla.
Alcuni pensieri su come far girare il tuo
Stai ruotando il tuo qui - cioè, ti viene in mente la tua soluzione a un problema in cui esiste già una buona pratica consolidata. Questo è stato discusso qui molte volte prima:
Rotolare il proprio sistema quando ci sono soluzioni consolidate porta raramente ovunque. Si aggiunge più complessità, ma raramente si aggiunge sicurezza. Se sei fortunato, almeno non peggiori le cose. Ma se sei sfortunato, non c'è limite ai problemi che puoi causare per te.
Nel tuo caso, non penso che tu abbia commesso errori fatali che portano a evidenti vulnerabilità. Ma chi lo sa? Non io, non tu. E quando implementi questo sistema complesso, ci sono così tanti altri posti in cui puoi commettere un piccolo errore e rovinarlo.
Detto questo, speculare su soluzioni alternative può essere un'esperienza di apprendimento molto utile e aiutarci a capire meglio le pratiche e i concetti esistenti. Quindi non c'è niente di sbagliato nel proporre e discutere sistemi diversi, a patto che non li facciano girare in produzione.