Generating a signed token. From the username or id and a timestamp a signed token is generated with a secret key. This is the link sent to the user. When the user submits the token is decrypted back and the user and timestamp retrieved and validated.
Stai parlando di chiavi segrete, token "firmati" e "decifrazione" (e più tardi, "salt") in un modo molto sciolto che suggerisce che probabilmente stai implementando questo errore. Quello che vorresti usare in questo caso è un codice di autenticazione dei messaggi , ad esempio HMAC-SHA256 , che le tue librerie crittografiche quasi certamente supportano già.
Sei molto saggio essere alla ricerca di attacchi di replay. La tua idea di inviare l'hash salato della password corrente come contesto, mentre non è buona se presa alla lettera, è sulla strada giusta. Quello che ti manca è che non hai bisogno di inserire l'hash nell'URL perché lo stai già archiviando ; tutto ciò che serve per inserire l'URL è l'informazione che consente al server di recuperare l'hash della password salata quando viene fatto clic sull'URL di ripristino. Il nome utente che stai reimpostando la password presumibilmente farebbe il trucco.
Ecco uno schizzo di una possibile soluzione. Innanzitutto, hai bisogno di un% sicuro disecret_key
. Un modo per farlo, che può farti risparmiare un sacco di mal di testa, è usare le chiavi effimero - invece di avere una chiave a lungo termine usata per molto tempo e che un attaccante può ancora, cosa fai è invece quando viene avviato il servizio di reimpostazione della password:
- Seleziona un
secret_key
di 128 bit a caso. Questo verrà sempre mantenuto in memoria, mai scritto su disco o in rete.
- Seleziona un
startup_uuid
unico. Userei un numero casuale o UUID.
Ciò significa che secret_key
è valido solo per la durata di un processo di ripristino chiavi: ogni volta che lo riavvii, la chiave viene scartata e ne viene generata una nuova. L'aspetto positivo è che il tuo servizio è molto più resistente alle chiavi rubate. Lo svantaggio è che i link di ripristino generati prima di un riavvio non vengono convalidati: lo scopo di startup_uuid
è rilevare tale caso e gestirlo in modo amichevole.
Quando viene richiesto un URL di reimpostazione della password per username
, il servizio di reimpostazione password esegue questa operazione:
- Scegli un timestamp di scadenza per il link di ripristino, ad esempio 15 minuti dopo l'ora corrente.
- Cerca la voce della password
username
della richiesta e recupera l'hash della password salata corrente.
- Costruisci un messaggio delimitato con% delimitato
reset_data
con i seguenti campi in ordine fisso:
- Il server elabora '
startup_uuid
;
- Il nome utente della richiesta;
- Il timestamp di scadenza selezionato;
- L'hash della password corrente dell'utente
- Calcola
reset_token = HMAC-SHA256(secret_key, reset_data)
- Costruisci un URL di ripristino con questi valori come parametri. ( NOTA: l'hash della password è non un parametro nell'URL di ripristino!)
- Il nome utente;
- Il timestamp di avvio del server;
- Il timestamp di scadenza;
- Il
reset_token
.
- Restituisce l'URL costruito.
Quando si riceve una richiesta dall'URL dell'URL di reimpostazione della password:
- Se
startup_uuid
della richiesta non è uguale a quella del server, il servizio è stato riavviato da quando è stato generato il collegamento. Non abbiamo più il vecchio secret_key
e quindi non possiamo verificare quella richiesta. L'utente dovrà ripetere la procedura di reimpostazione della password.
- Se l'ora corrente è successiva al valore di data e ora di scadenza dell'URL, il link è scaduto, quindi non accettarlo.
- Cerca l'hash della password salata per il nome utente della richiesta.
- Costruisci un messaggio delimitato non modificato
reset_data
come sopra.
- Verifica che questo messaggio
reset-data
corrisponda al reset_token
incluso nell'URL. Assicurati di farlo in sicurezza con un confronto di parità costante-time.
- Se la verifica ha esito positivo, procedi e ripristina la password dell'utente.
Questo protocollo ha queste virtù:
- Le chiavi segrete sono effimere e vengono sempre conservate nella memoria, quindi anche se qualcuno ruba in qualche modo una chiave è valida solo fino al prossimo riavvio.
- L'hash della password da ripristinare viene utilizzato come input per HMAC. Se un utente tenta di reimpostare una password che è già stata reimpostata o modificata in altro modo, la verifica del token di reimpostazione non avrà esito positivo.
- A differenza della tua proposta, la password con hash non viene mai divulgata.