Ho un piano per la gestione dell'autenticazione e della crittografia dei messaggi, e mi piacerebbe che altri condividessero la conoscenza della crittografia per farmi sapere se il mio approccio è corretto o come dovrebbe essere migliorato.
Le app client si collegheranno al mio server tramite un socket TCP / IP. Mi piacerebbe evitare SSL / TLS. Sul server, sarò l'archiviazione per ogni utente (e cambiato ogni volta che l'utente cambia la password): un sale a caso, l'hash della codifica UTF-8 della loro parola d'accesso più il sale, una chiave simmetrica, e, eventualmente, la cifratura di quella chiave simmetrica (se la chiave simmetrica è casuale, invece di essere derivata dalla password / sale).
Quando gli utenti effettuano il login, il client invierà il nome utente, il server invierà il sale e il client invierà l'hash. Se l'hash corrisponde, il server invierà la chiave simmetrica crittografata e il client la decrittografa e utilizzerà la chiave simmetrica decrittografata per i successivi messaggi crittografati. Se riesco a ricavare la chiave simmetrica dalla password / sale, non sarà necessario calcolare e memorizzare la chiave simmetrica crittografata o inviarla al client per la decrittografia.
Per hashing la password / sale, mi stava progettando su un solo utilizzando SHA-384, ma è stato fatto notare a me (da zaph) che dovrei "iterare su un HMAC con un sale casuale per circa una durata 100 ms e salva il sale con l'hash ". Non voglio usare un'altra libreria, quindi penso che questo è ciò che intendeva:
int
i;
byte[]
passwordBytes,
saltBytes,
saltedPasswordBytes,
hash;
passwordBytes = Encoding.UTF8.GetBytes( "MyPass" );
using ( RNGCryptoServiceProvider rngProvider = new RNGCryptoServiceProvider() )
{
saltBytes = new byte[ 128 ];
rngProvider.GetBytes( saltBytes );
}
// Salt the password.
saltedPasswordBytes = new byte[ passwordBytes.Length + saltBytes.Length ];
System.Buffer.BlockCopy(
passwordBytes, 0, saltedPasswordBytes, 0, passwordBytes.Length );
System.Buffer.BlockCopy(
saltBytes, 0, saltedPasswordBytes, passwordBytes.Length, saltBytes.Length );
using ( HMACSHA512 hmac = new HMACSHA512( saltedPasswordBytes ) )
{
// Get the hash of the salted password.
hash = hmac.ComputeHash( saltedPasswordBytes );
// Iterate, getting the hash of the hash.
for ( i = 0; i < 2000; i++ )
hash = hmac.ComputeHash( hash );
}
Un'altra grande preoccupazione è come crittografare la chiave simmetrica. Mi è stato originariamente pensato di AES, e l'invio della chiave simmetrica crittografata al cliente, ma mi chiedo se devo usare qualcosa come sopra, ma varia leggermente, come mettere uno zero nella parte anteriore dei byte di password salate prima di hashing esso e quindi prendendo i primi 32 byte di quello per la chiave. In questo modo, non avrò nemmeno bisogno di crittografare la chiave simmetrica.
Il mio prossimo problema è la crittografia dei messaggi. Dopo aver letto la pubblicazione NIST 800-38A e i post del blog, sono così confuso riguardo alle modalità di cifratura. Il CTR suona bene, ma non è supportato in .NET e non voglio usare librerie di terze parti. Poiché i miei messaggi possono essere piuttosto lunghi e possono avere molte parti ripetute, ECB sembra una cattiva scelta. Usando un altro, come CBC, ora ho bisogno di trattare con il IV. Un approccio che ho letto è quello di utilizzare un nuovo IV casuale con ogni messaggio e inviarlo prima dei byte crittografati. Suona bene per il primo messaggio inviato, ma mi piacerebbe mantenere i messaggi piccoli, quindi stavo pensando di alterare l'IV per ogni messaggio successivo, usando un algoritmo applicato da entrambe le parti. Ho letto che l'IV per i messaggi successivi deve essere imprevedibile, quindi suppongo di dover prendere l'hash di un contatore e XOR quello del IV precedente o qualcosa del genere.
Quindi, esperti, sto andando su questo nel modo giusto? L'iterazione è corretta? È una buona idea usare questo approccio (leggermente diverso, come con uno zero davanti alla password e al sale) per determinare la chiave simmetrica? Quale modalità di cifratura (e approccio IV, se applicabile) dovrei usare per crittografare i messaggi?
Grazie.