2009-04-02 22 views
6

Ho un messaggio che sto passando a me stesso che sarà soggetto ad attacchi man-in-the-middle. Per questo motivo, sono preoccupato per l'integrità del messaggio che viene mantenuto tra il momento in cui lo invio e il momento in cui lo ricevo.Mantenimento dell'integrità del messaggio

Si deve presumere che una volta inviato il messaggio a me stesso, nessuna informazione sul messaggio inviato sarà disponibile per me in futuro. Il messaggio è completamente autonomo.

A tal fine, so che deve cancellare il contenuto del messaggio e confrontare gli hash prima di inviare il messaggio, e dopo aver inviato il messaggio, se sono diversi, il messaggio è stato manomesso.

Ovviamente, se il man-in-the-middle sa che l'hash è in realtà solo l'hash del contenuto del messaggio, così com'è, quindi poiché il messaggio è autonomo, può semplicemente creare nuovi contenuti e applicare lo stesso algoritmo di hash ai contenuti.

La domanda è: a quali lunghezze dovrei andare a randomizzare il contenuto del messaggio quando si genera l'hash? Quando raggiunge il punto di rendimenti decrescenti?

In questo scenario, ho un set di coppie chiave/valore. A tal fine, i passaggi che so di dover prendere sono:

  1. Aggiungere un sale al messaggio. Il sale è un segreto per il resto del mondo. Viene allegato al contenuto del messaggio prima dell'hashing.
  2. Ordinare le coppie chiave/valore in modo coerente prima di generare l'hash.
  3. Mentre non è direttamente rilevante, un timestamp verrà aggiunto al contenuto di ciascun messaggio prima dell'hash, per impedire attacchi di riproduzione.

Questi sono i passaggi facoltativi che sto considerando:

  1. Trasformare le chiavi prima di ordinarli. Ho preso in considerazione la possibilità di invertirli, quindi di ordinare per numero/chiave.
  2. Giocare con i separatori che separano coppie chiave/valore (sia per il separatore per la chiave/valore che per il separatore per la coppia).

NOTA

privacy dei messaggi è non un requisito qui, quindi non sto cercando per la crittografia. I valori devono essere essere trasmessi in testo normale.

Infine, quali algoritmi di hashing dovrei evitare?


Specifiche

Ho un sito ASP.NET MVC, che ho un controller che gestisce convalida dell'input e persistenza.

Se (basato su un euristico, non è importante quale) viene determinato che l'input è un tentativo di spam automatico, viene creato un modello di IDictionary<string, string> con i valori di input e un ViewResult viene inviato a una pagina CAPTCHA generale.

In questa visualizzazione, nel modulo che contiene il controllo CAPTCHA, il contenuto di IDictionary<string, string> verrà scritto nei campi di input nascosti e l'azione del modulo sarà la stessa azione in cui i contenuti sono stati originariamente pubblicati. In questo modo, MVC può raccogliere i valori quando viene inviato nuovamente il modulo.

È per questo che non riesco a crittografare le coppie chiave/valore (o forse posso e dovrei, dimmi perché e come!).

Naturalmente, ho bisogno di aggiungere un altro valore, che contiene il contenuto del messaggio con hash. Se questo valore è presente, il controller verificherà che l'integrità del messaggio sia mantenuta e che permetta di mantenere l'input se è presente.

Soluzione

ho scelto di andare con la classe SignedCms nello spazio dei nomi System.Security.Cyrptography.Pkcs, che rappresenta il signging e il controllo dei CMS/PKCS # 7 messaggi.

Elaborare, ho creato un certificato auto-rilasciato con Makecert.exe e poi nel mio codice, io uso l'esempio qui per firmare digitalmente i dati:

http://blogs.msdn.com/shawnfa/archive/2006/02/27/539990.aspx

Ora, si deve si tratta di mantenere la password della chiave privata esportata protetta, così come la sicurezza sul server, il che rende meno la programmazione.

Dovrò aggiungere una chiave extra per il timestamp per gli attacchi di riproduzione, ma non sarà troppo difficile.

La risposta va a Kalium, non per la sua initial post, ma per i suoi follow-up commenti che indicavano la strada alle firme digitali, e alla fine la mia scoperta di come utilizzarle in .NET.

Grazie a tutti coloro che hanno contribuito.

risposta

6

Penso che PGP/GPG sia quello che vuoi qui.

+0

@ Kalium: No, la privacy dei messaggi non è un problema ed è un po 'eccessivo. In effetti, la trasparenza dei messaggi è un requisito. – casperOne

+1

È ancora probabilmente l'opzione migliore per garantire l'integrità dei messaggi. Non è necessario crittografarlo, basta firmarlo. Potresti anche inviare la chiave pubblica con esso. – Kalium

+0

@ Kalium: A tal fine, hai qualche link a buone risorse PGP/GPG in .NET? Inoltre, che dire del problema "segreto condiviso"? Il fatto di firmare l'hash con una chiave asimmetrica rende la chiave privata il segreto e nega la necessità di disporre diversamente i dati per l'hash? – casperOne

1

Si desidera un Digitally Signed message. Utilizzando GPG puoi firmare il messaggio senza lo crittografandolo. Ma nessuno sarà in grado di manometterlo, perché loro non possono generare l'hash - solo perché l'hash utilizza la chiave privata.

0

Probabilmente si dovrebbe firmare digitalmente il messaggio (quindi PGP/GPG raccomandato da Kalium è rilevante come opzione). Qualsiasi hash puro che è possibile creare può essere ricreato dall'attaccante. La firma digitale - utilizzando la tua chiave privata di firma in modo che la tua chiave pubblica possa essere utilizzata per verificarlo - è la soluzione. Qualsiasi altra cosa è un esercizio di futilità.

0

Supponendo che non si può passare tutte le informazioni su un canale "sicura" (vale a dire l'hash) ecco come si dovrebbe fare:

  1. Hash il messaggio, quindi firmare l'hash con una chiave privata. Includere l'hash firmato nel messaggio.
  2. Quando si riceve il messaggio, utilizzare la chiave pubblica per decrittografare l'hash firmato e verificare che corrisponda all'hash reale del messaggio.

Un utente malintenzionato non è in grado di "falsificare" un messaggio, poiché è necessario disporre della chiave privata per crittografare il nuovo hash.

Come altri hanno già detto, questa è la firma digitale semplicemente vaniglia e può essere gestito da qualcosa come PGP/GPG

2

L'approccio in avanti più dritto per consentire l'applicazione per verificare che i propri messaggi non siano state manomesse sarebbe quello di utilizzare un codice di autenticazione del messaggio hash con chiave. Il messaggio viene inviato in chiaro, ma include anche un hash per impedire la manomissione. L'hash dipende sia dal contenuto del messaggio che da una chiave segreta. L'uomo nel mezzo non può falsificare un hash su un messaggio alterato senza conoscere la chiave. Poiché la tua applicazione crea e verifica i messaggi, non ha mai bisogno di rivelare la chiave segreta.

Raccomando in particolare l'implementazione descritta in RFC-2104 http://www.ietf.org/rfc/rfc2104.txt poiché è stata attentamente studiata per evitare la maggior parte delle possibili insidie.

Se i messaggi devono essere verificati per l'autenticità da parti non fidate, è necessario utilizzare uno schema di firma digitale.

È probabile che vi sia un supporto per entrambe le librerie .Net. Miles ha fornito (come commento) un collegamento alla pagina Web MSDN per le funzioni della libreria .Net che implementano un HMAC con chiave utilizzando l'hash SHA1: http://msdn.microsoft.com/en-us/library/system.security.cryptography.hmacsha1.aspx.

+0

+1 HMAC. Le firme digitali asimmetriche suggerite dalla maggior parte delle altre risposte sono eccessive per questo problema. – Miles

+0

http://en.wikipedia.org/wiki/HMAC - http://msdn.microsoft.com/en-us/library/system.security.cryptography.hmacsha1.aspx – Miles

Problemi correlati