2009-06-09 14 views
11

Fondamentalmente voglio usare System.Security.Cryptography.AesManaged (o una classe migliore, se pensi che ce ne sia uno?) Per prendere un array di byte e creare un altro array di byte crittografato, usando una data chiave simmetrica (presumo che i ' Ne avrò bisogno?).Come utilizzare "System.Security.Cryptography.AesManaged" per crittografare un byte []?

Ho anche bisogno del modo per invertire questa procedura.

Il punto è che posso crittografare le password memorizzate. Presumo che ci sia un modo semplice per farlo?

Grazie

risposta

7

Simple encrypting and decrypting data in C#.

Edit: per le password, mi consiglia di utilizzare BCrypt invece di fare una crittografia a due vie, a meno che non si ha realmente bisogno di recuperare la password originale. Normalmente hai solo bisogno del fatto che qualcuno conoscesse la password, non la password stessa.

+0

Sembra buono, ma che cos'è un IV? Pensavo avessi solo bisogno di una chiave da 16 byte? – Chris

+0

http://en.wikipedia.org/wiki/Initialization_vector. Puoi aumentare la forza se metti cose a caso lì dentro, ma potresti usare anche degli zero. –

+0

Ho bisogno delle password per passarle su un altro servizio. – Chris

10

MODIFICA: Notato modifica di eed3si9n ... Sono d'accordo, la crittografia simmetrica è una cattiva scelta per le password. Utilizzare hash (e non MD5). Ecco a very complete example.

Un semplice esempio:

byte[] clear = GetCleartext(); 
HashAlgorithm sha2 = SHA256CryptoServiceProvider.Create(); 
byte[] hashed = sha2.ComputeHash(clear); 

Per convalidare una password corretta, si correrebbe lo stesso calcolo sopra la password fornita, e confrontare il risultato con l'hash che avete nel vostro database.

È buona norma aggiungere salt (dati casuali) al testo in chiaro per evitare rainbow table attacks. Fondamentalmente, aggiungi un valore generato casualmente noto, unico per quell'utente, al testo in chiaro prima dell'hashing.

+0

E un chiarimento: il valore del sale deve essere mantenuto insieme all'hash per i confronti successivi. E generare un nuovo salt ogni volta che l'utente cambia la password. – devstuff

+3

Ho bisogno delle password per passarle su un altro servizio. – Chris

11

Ecco quello che ho fatto, alla fine, ispirato (una versione precedente di) risposta di Michael:

private string Encrypt(string input) 
{ 
    return Convert.ToBase64String(Encrypt(Encoding.UTF8.GetBytes(input))); 
} 
private byte[] Encrypt(byte[] input) 
{ 
    PasswordDeriveBytes pdb = new PasswordDeriveBytes("hjiweykaksd", new byte[] { 0x43, 0x87, 0x23, 0x72, 0x45, 0x56, 0x68, 0x14, 0x62, 0x84 }); 
    MemoryStream ms = new MemoryStream(); 
    Aes aes = new AesManaged(); 
    aes.Key = pdb.GetBytes(aes.KeySize/8); 
    aes.IV = pdb.GetBytes(aes.BlockSize/8); 
    CryptoStream cs = new CryptoStream(ms, aes.CreateEncryptor(), CryptoStreamMode.Write); 
    cs.Write(input, 0, input.Length); 
    cs.Close(); 
    return ms.ToArray(); 
} 
private string Decrypt(string input) 
{ 
    return Encoding.UTF8.GetString(Decrypt(Convert.FromBase64String(input))); 
} 
private byte[] Decrypt(byte[] input) 
{ 
    PasswordDeriveBytes pdb = new PasswordDeriveBytes("hjiweykaksd", new byte[] { 0x43, 0x87, 0x23, 0x72, 0x45, 0x56, 0x68, 0x14, 0x62, 0x84 }); 
    MemoryStream ms = new MemoryStream(); 
    Aes aes = new AesManaged(); 
    aes.Key = pdb.GetBytes(aes.KeySize/8); 
    aes.IV = pdb.GetBytes(aes.BlockSize/8); 
    CryptoStream cs = new CryptoStream(ms, aes.CreateDecryptor(), CryptoStreamMode.Write); 
    cs.Write(input, 0, input.Length); 
    cs.Close(); 
    return ms.ToArray(); 
} 
+6

Dato il tuo codice sopra, avrai sempre la stessa chiave, il che è buono, ** ma alla fine otterrai anche la stessa IV, il che è pessimo **. Sono abbastanza sicuro che l'IV dovrebbe essere specifico per i dati che stai crittografando, mentre la chiave può essere "globale". –

0

Il PO afferma che devono passare le credenziali a un altro servizio, che è un problema completamente diverso da quello di memorizzazione delle password e la verifica.

A seconda della quantità di controllo che si ha sul servizio partner o su ciò che espongono, le migliori soluzioni coinvolgono un fornitore o approcci standard del settore come Kerberos, SAML o altro token al portatore stabile e sicuro significa flusso di fiducia. Questo è un argomento profondo.

Ma supponiamo che sia necessario passare le credenziali tramite Basic Auth SSL/TLS. Quindi ora è necessario memorizzarli in modo sicuro in modo reversibile. Per risolvere questo problema, ho avuto successo con la chiave segreta trasmessa utilizzando una chiave privata del certificato. Ciò offre una certa protezione del tuo segreto dal sistema operativo e consente alle persone OPS di gestire le chiavi, il che è auspicabile. L'account utilizzato per eseguire il processo deve disporre dei diritti per vedere la chiave privata, che quindi termina la catena di fiducia sul sistema operativo.

È ancora possibile che si debba pensare alla rotazione delle chiavi, che richiederà di memorizzare un numero di versione con il testo cifrato.

Inoltre, SecureString potrebbe essere di interesse, ma fino a quando tutte le API .NET consentono a SecureString di essere passato come parte di una credenziale, spesso si finisce con una stringa sull'heap gestito che non si può distruggere.

In ogni caso, questa non è una risposta alimentata a cucchiaio con codice, ma per esperienza, ho scoperto che gestire la catena di segreti è sempre un problema, e se non è possibile terminare su un'infrastruttura hardened come Active Directory, certificati sono la prossima cosa migliore.

Problemi correlati