2010-01-27 28 views
10

Sono in procinto di eseguire una routine di crittografia/decrittografia simmetrica in C#. So che ci sono state alcune domande su questo argomento prima, ma la maggior parte delle risposte sembra riguardare la filosofia della crittografia piuttosto che fornire un codice reale.Codifica simmetrica/decodifica in .NET

Aggiornamento: Mi piacerebbe molto vedere del codice, piuttosto che solo collegamenti. Grazie molto!

+1

Rijndael non è simmetrico? –

+0

Credo che sia –

+1

Consiglierei di usare Rijndael, quindi :) –

risposta

11

Vedere il codice di esempio nella parte inferiore di this page.

copia-incolla qui:

int Rfc2898KeygenIterations= 100; 
int AesKeySizeInBits = 128; 
String Password = "VerySecret!"; 
byte[] Salt = new byte[16]; 
System.Random rnd = new System.Random(); 
rnd.NextBytes(Salt); 
byte[] rawPlaintext = System.Text.Encoding.Unicode.GetBytes("This is all clear now!"); 
byte[] cipherText= null; 
byte[] plainText= null; 
using (Aes aes = new AesManaged()) 
{ 
    aes.Padding = PaddingMode.PKCS7; 
    aes.KeySize = AesKeySizeInBits; 
    int KeyStrengthInBytes= aes.KeySize/8; 
    System.Security.Cryptography.Rfc2898DeriveBytes rfc2898 = 
     new System.Security.Cryptography.Rfc2898DeriveBytes(Password, Salt, Rfc2898KeygenIterations); 
    aes.Key = rfc2898.GetBytes(KeyStrengthInBytes); 
    aes.IV = rfc2898.GetBytes(KeyStrengthInBytes); 
    using (MemoryStream ms = new MemoryStream()) 
    { 
     using (CryptoStream cs = new CryptoStream(ms, aes.CreateEncryptor(), CryptoStreamMode.Write)) 
     { 
      cs.Write(rawPlaintext, 0, rawPlaintext.Length); 
     } 
     cipherText= ms.ToArray(); 
    } 

    using (MemoryStream ms = new MemoryStream()) 
    { 
     using (CryptoStream cs = new CryptoStream(ms, aes.CreateDecryptor(), CryptoStreamMode.Write)) 
     { 
      cs.Write(cipherText, 0, cipherText.Length); 
     } 
     plainText = ms.ToArray(); 
    } 
} 
string s = System.Text.Encoding.Unicode.GetString(plainText); 
Console.WriteLine(s); 
+5

Ewww, usando il Random non sicuro per creare il sale? Brutta cattiva idea – blowdart

+6

@blowdart - No. Salt e IV devono essere il più unici possibile, ma generarli in modo sicuro non significa nulla. La scelta casuale casuale è casuale e difficile da prevedere, e non ti importa se la tua IV o il sale sono previsti - sono comunque trasmessi/archiviati in testo in chiaro. – orip

+0

@blowdart - Concedo il tuo punto su IV in modalità CBC. Tuttavia non mantiene il sale in PBKDF2. – orip

2

di convertire il testo, chiave e vettore di inizializzazione ai byte prima usando la codifica della vostra scelta. Quindi utilizzare il provider triplo DES, come dimostrato qui:

http://msdn.microsoft.com/en-us/library/system.security.cryptography.tripledes.aspx

O quello per AES, se si pensa Triple DES è troppo vecchia scuola, o qualsiasi altra cosa.

Per curiosità, come state progettando di comunicare la chiave segreta?

+1

Quindi stai provando a crittografare i dati per impedire all'utente di leggerli? –

+0

Per DES, la chiave e IV possono essere qualsiasi stringa di caratteri, giusto? –

+5

Hardcoding la chiave nell'origine di un'applicazione .NET è irrimediabilmente insicura. Tutto quello che l'utente deve fare è scaricare Reflector e la chiave è proprio lì in bella vista. –

5

Bene per gli starter le chiavi non sono stringhe, le chiavi sono blob binari. PlainText è lo stesso, non è in realtà testo, di nuovo è un blob binario.

Ora, naturalmente, è possibile convertire le stringhe di byte array utilizzando Encoding.UTF8.GetBytes(message), tuttavia quando si converte i tasti avanti e indietro è un po 'più complicato, di solito uso Convert.ToBase64String e Convert.FromBase64String.

Non dimenticate che i cifrari a blocchi hanno bisogno anche un'altra cosa, il vettore di inizializzazione, quindi in realtà i vostri metodi di firme dovrebbe essere

byte[] Encrypt(byte[] plainText, byte[] key, byte[] iv) 

byte[] Decrypt(byte[] cipherText, byte[] key, byte[] iv) 

La chiave e IV deve essere numeri casuali crittograficamente sicuro, don' t digitarli e non usare la funzione Random di C#. Le dimensioni della chiave e della IV dipendono dall'algoritmo di cifratura utilizzato e sono accessibili dalle proprietà delle classi.

Per generare una CSRPNG fai qualcosa come

RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider(); 
byte[] key = new byte[algorithm.KeySizeValue/8]; 
rng.GetBytes(key); 
byte[] iv = new byte[algorithm.BlockSizeValue/8]; 
rng.GetBytes(iv); 

È inoltre possibile utilizzare la classe Rfc2898DeriveBytes per derivare una chiave e IV da una password e un sale, ma ancora una volta il sale dovrebbe essere un numero casuale crittograficamente sicuro . Dovresti anche notare quando crei un algoritmo simmetrico una chiave sicura e IV viene generata per te.

In questo modo è possibile scegliere la codifica corretta per il testo, sia esso UTF8, ASCII o qualsiasi altra cosa. I collegamenti hanno abbastanza campioni quindi tagliare e incollare qui è piuttosto inutile.

+1

Gli IV non hanno bisogno di essere crittograficamente sicuri, solo le chiavi lo fanno. – orip

+1

Non vero, in modalità CBC, l'IV deve essere imprevedibile al momento della crittografia – blowdart

+1

Grazie, non ne era a conoscenza. – orip

4

Ecco una soluzione semplice che ho trovato su un forum VB.NET e convertito in C#. Mi ha sicuramente aiutato a capire meglio l'argomento.

// Shamelessly lifted from http://discuss.itacumens.com/index.php?topic=62872.0, 
// then converted to C# (http://www.developerfusion.com/tools/convert/vb-to-csharp/) and 
// changed where necessary. 
public class Encryptor 
{ 
    private static SymmetricAlgorithm _cryptoService = new TripleDESCryptoServiceProvider(); 
    // maybe use AesCryptoServiceProvider instead? 

    // vector and key have to match between encryption and decryption 
    public static string Encrypt(string text, byte[] key, byte[] vector) 
    { 
     return Transform(text, _cryptoService.CreateEncryptor(key, vector)); 
    } 

    // vector and key have to match between encryption and decryption 
    public static string Decrypt(string text, byte[] key, byte[] vector) 
    { 
     return Transform(text, _cryptoService.CreateDecryptor(key, vector)); 
    } 

    private static string Transform(string text, ICryptoTransform cryptoTransform) 
    { 
     MemoryStream stream = new MemoryStream(); 
     CryptoStream cryptoStream = new CryptoStream(stream, cryptoTransform, CryptoStreamMode.Write); 

     byte[] input = Encoding.Default.GetBytes(text); 

     cryptoStream.Write(input, 0, input.Length); 
     cryptoStream.FlushFinalBlock(); 

     return Encoding.Default.GetString(stream.ToArray()); 
    } 
} 
Problemi correlati