Per svariati motivi, ho bisogno di utilizzare l'autenticazione digest per un server REST che ho creato.
Ho elaborato un "miglioramento" che a mio parere rafforza l'algoritmo contro gli attacchi MD5 senza gravare sui client. Quali problemi puoi vedere con il mio algoritmo?
Introduzione
- Client è un'applicazione personalizzata scritta in C #.
- Server è un server REST basato su JAX-RS scritto in Java e in esecuzione su Tomcat.
- Tutto il traffico tra client e server è crittografato tramite SSL / TLS.
-
Il database contiene un user_table con le seguenti colonne:
- user_id: chiave primaria
- password_hash: varchar not null
- salt: varchar not null
- iteration_count: intero
Autenticazione del digest (RFC2617)
L'autenticazione del digest utilizza i seguenti calcoli:
nonce: server-generated number used once
nonceCount: server-generated increasing value (prevents replay attacks)
cnonce: client-generated number used once
qop: quality of protection ("auth")
method: typically one of "GET", "POST", "PUT", etc.
HA1 = MD5(username:realm:password)
HA2 = MD5(method:digestURI)
response = MD5(HA1:nonce:nonceCount:cnonce:qop:HA2)
Il valore HA1
è memorizzato nel database come valore di hash della password. Durante l'autenticazione, il client calcola il valore di response
dalle intestazioni http WWW-authenticate
http. Il server calcola anche il valore response
utilizzando la versione memorizzata di HA1
e confronta il valore ricevuto dal client. Se sono uguali, il client è autenticato.
MD5 non è più considerato sicuro. Le collisioni possono essere trovate in poche ore utilizzando l'hardware commodity.
Utilizzo di PBKDF2 per rafforzare il digest
- Il cliente ottiene il nome utente e la password in testo semplice dall'utente.
- Il client richiede il conteggio di sale e iterazione per user_id dal server. Il server invia anche il conteggio di iter predefinito corrente (che potrebbe essere diverso da quello utilizzato per questo utente).
- Il client calcola una chiave segreta a 128 bit utilizzando PBKDF2 (password, salt, conteggio di iterazione specifico dell'utente). La chiave segreta è codificata come una stringa esadecimale.
- Il client calcola
HA1
utilizzando il nome utente, il realm e la chiave con codifica esadecimale. Questo valore diHA1
viene utilizzato in un'autenticazione digest standard. - Il server ottiene l'hash della password dal database. L'hash della password è il
HA1
calcolato in precedenza utilizzando la stessa chiave segreta derivata da PBKDF2. Il server confronta il% co_de calcolato con il valoreresponse
inviato dal client (autenticazione digest standard). Se i due valori diresponse
sono uguali, il client viene autenticato. - Se il conteggio dell'iterazione specifico dell'utente restituito al client è diverso dal conteggio iterazione predefinito, il client calcola un nuovo
response
utilizzando PBKDF2 e il nuovo conteggio dell'iterazione. Il client chiama un metodoHA1
sul server REST per aggiornare la colonna dell'hash della password utilizzando il nuovo valore. Questo passaggio consente di aggiornare l'algoritmo con conteggi di iterazioni più grandi man mano che l'hardware diventa più veloce.
L'algoritmo modificato non si basa sulla forza di MD5 per proteggere l'hash della password, poiché la difficoltà di calcolare l'hash della password dipende da PBKDF2 (che può utilizzare un hash SHA-1 o SHA-256).
Ci sono evidenti difetti di sicurezza in questo algoritmo modificato?