Sto progettando un semplice webservice e voglio usare HMAC per l'autenticazione al servizio.
Per lo scopo di questa domanda abbiamo:
- un servizio web su example.com
- una chiave segreta condivisa tra un utente e il server [K]
- un ID utente noto all'utente e al server (ma non necessariamente segreto) [D]
- un messaggio che vogliamo inviare al server [M]
L'implementazione HMAC standard implicherebbe l'uso della chiave segreta [K] e del messaggio [M] per creare l'hash [H], ma sto riscontrando problemi con questo. Il messaggio [M] può essere piuttosto lungo e tende a essere letto da un file. Ho trovato molto difficile produrre un hash corretto in modo coerente su più sistemi operativi e linguaggi di programmazione a causa di caratteri nascosti che lo rendono in vari formati di file. Questa è ovviamente una cattiva implementazione dal lato client (100%), ma vorrei che questo servizio web fosse facilmente accessibile e non avesse problemi con diversi formati di file.
Stavo pensando ad un'alternativa, che consentirebbe l'uso di una stringa casuale [R] di breve durata (5-10 caratteri) anziché del messaggio per l'autenticazione, ad es.
H = HMAC(K,R)
L'utente passa quindi la stringa casuale al server e il server controlla il lato server HMAC (usando una stringa casuale + segreto condiviso).
Per quanto posso vedere, questo produce i seguenti problemi:
- Non c'è integrità del messaggio - questa è ok l'integrità del messaggio è non importante per questo servizio
- Un utente potrebbe riutilizzare l'hash con un messaggio diverso - Posso vedere 2 modi per aggirare questo problema
- Combina la stringa casuale con un timestamp in modo che l'hash sia valido solo per un determinato periodo di tempo
- Consenti solo che ogni stringa casuale venga utilizzata una volta
- Poiché il client ha il controllo della stringa casuale, è più semplice cercare le collisioni
Devo sottolineare che il motivo principale per l'autenticazione è l'implementazione della limitazione della velocità sul servizio API. Non c'è bisogno di integrità dei messaggi, e non è un grosso problema se qualcuno può falsificare una singola richiesta (ma lo è se è in grado di falsificare molto velocemente un numero molto grande).
So che la risposta corretta è quella di assicurarsi che il messaggio [M] sia lo stesso su tutte le piattaforme / lingue prima di cancellarlo. Ma, escludendo l'equazione, la proposta sopra è accettabile come seconda migliore?