Spingendo gli hash delle password sul client, li esporresti agli attacchi brute force offline. Questo può essere del tutto accettabile se le password sono sufficientemente forti. Ma questa è un'assunzione pericolosa da fare.
Potresti chiedere ad ogni utente di confermare che vuole che il proprio hash sia pubblicato (dopo aver spiegato il rischio per loro). Ma ci sono molti utenti che sarebbero felici di dire che capiscono il rischio e hanno scelto una password sufficientemente solida anche se ciò che effettivamente scelgono era password12345!!!
A questo punto dovrai valutare l'importanza di questa funzionalità rispetto al rischio di consentire agli utenti di spararsi ai piedi.
C'è tuttavia un altro svantaggio nella progettazione che è quello di autenticare gli aggiornamenti resi offline. Affidarsi al client per convalidare l'utente non è abbastanza buono.
Memorizzando la password dell'utente insieme all'aggiornamento e inviandoli entrambi al server una volta online si risolverebbe il problema di eseguire solo la validazione lato client. Ma introdurrai tre nuovi problemi:
- Non acquisisce credenziali digitate erroneamente quando si inseriscono gli aggiornamenti. E in seguito quando tali credenziali vengono verificate dal server, l'utente che le ha digitate in primo luogo potrebbe non essere in giro per risolvere il problema.
- L'aggiornamento sarebbe malleabile. Sarebbe banale modificare l'aggiornamento mentre è memorizzato sul dispositivo client per farlo eseguire un aggiornamento diverso una volta arrivato sul server.
- Si memorizzano le password in chiaro sul dispositivo che è un grande no-no securitywise.
Non vedo alcun modo per prevenire la forza bruta offline delle password, pur consentendo la convalida della password nel momento in cui viene inserito un aggiornamento, e tale convalida è necessaria per ragioni di usabilità.
L'approccio che prendo quindi è di creare una coppia di chiavi pubbliche basata sulla password degli utenti e su un valore salt e utilizzare la chiave privata corrispondente per firmare l'aggiornamento. Ciò significa che l'aggiornamento non è più malleabile e che la password non deve essere memorizzata e trasmessa, ma solo archiviare e trasmettere la firma.
Ovviamente il cliente dovrebbe comunque conoscere salt e username per generare una transazione correttamente firmata. E sarebbe necessario conoscere la chiave pubblica o un hash per verificarlo in primo luogo, il che consente attacchi di forza bruta offline.
Puoi troncare il lato client verificato dell'hash su un solo byte, il che rende gli attacchi offline a forza bruta meno fattibili e ha ancora il 99% di possibilità di rilevare password errate sul lato client.
Sul lato server, dovresti ancora verificare la chiave pubblica trasmessa utilizzando un hash salato per assicurarti di ricevere solo transazioni valide.
Ovviamente qualsiasi progetto per l'applicazione che stai progettando lascia molto spazio per errori, quindi avere la progettazione finale e la revisione del codice da parte di più professionisti della sicurezza è una necessità per garantire che il risultato finale sia sicuro.