Non mi è chiaro esattamente il motivo per cui stai implementando un meccanismo di autenticazione così complesso. Le soluzioni di autenticazione homegrown sono notoriamente difficili da correggere. Quindi i miei primi pensieri sono di cercare di guidarvi verso meccanismi più standard.
In sintesi, la mia raccomandazione è di usare username / password per l'autenticazione. Se hai una buona ragione per non farlo, usa l'autenticazione reciproca SSL. E se hai davvero un buon motivo per non farlo, usa il tuo metodo suggerito con la modifica del timestamp su un nonce generato sul lato server.
Dettagli segui ...
Opzione 1: usa semplicemente nome utente / password per l'autenticazione. Non menzioni il motivo per cui non stai scegliendo questo percorso più comune. Forse stai sperando in un più alto grado di sicurezza?
Opzione 2: utilizza l'autenticazione reciproca TLS / SSL . Questo è un vero e provato standard supportato da quasi tutti i browser Web e la libreria TLS. Nell'autenticazione reciproca, il client ha una chiave privata e un certificato X.509, simile al server. Quando viene avviata la connessione SSL, utilizza non solo il certificato del server, ma anche quello del client. Entrambi i lati della comunicazione possono confermare il partito con cui stanno comunicando. A differenza del certificato del server, il certificato del cliente non deve necessariamente essere firmato da un'autorità di certificazione. Ciò significa che potrebbe essere un certificato autofirmato o creato dalla tua autorità di certificazione. Tutto ciò che conta è che il server possa convalidare che è il certificato giusto per un utente specifico. La mia preferenza è semplicemente di memorizzare il certificato (in realtà l'impronta digitale del certificato) nel database degli utenti. Ciò consente una revoca semplice poiché significa semplicemente eliminare il certificato revocato dal DB.
In base alla comprensione limitata del tuo progetto, non vedo alcun vantaggio per la tua soluzione proposta rispetto all'autorizzazione reciproca SSL. Stai ricreando parti del protocollo di autenticazione reciproca invece di utilizzare solo una soluzione consolidata.
Opzione 3: la tua soluzione di homegrown. Non vedo problemi a passare il nonce nello stesso messaggio della firma. Dato che questo viene fatto su SSL, solo il client e il server potrebbero vedere queste informazioni. Quindi non importa se il server ottiene il nonce nel messaggio o "conosce" il nonce da una parte precedente della conversazione. In entrambi i casi, il server ha sia il nonce che la sua firma e nessun altro dovrebbe avere accesso a queste informazioni.
Per quanto riguarda la sconfitta di un attacco di replay (cosa presumo tu intenda per "rogue digest"), sono non entusiasta dell'utilizzo di un nonce generato dal lato client. Penso che sia più sicuro avere il server che passa il nonce al client e poi lasciare che il client firmi quei dati. Ciò richiede un ulteriore giro di comunicazione, ma poiché stiamo discutendo di conversazioni longeve in questo scenario, penso che questo dovrebbe essere OK. Una volta che ti sposti con un nonce scelto dal lato server, puoi semplicemente utilizzare un numero casuale crittograficamente sicuro come nonce e store questo nonce sul server. Il server può quindi gestire la durata di vita del nonce. Inoltre, non sono un grande fan dell'utilizzo di timestamp che si estendono su computer come, anche nel 2016, la sincronizzazione dell'orologio tra server e client può essere una seccatura.