2010-01-27 16 views
10

Ich bin nach einer symmetrischen Verschlüsselung/Entschlüsselung Routine in C#. Ich weiß, dass es zu diesem Thema schon einige Fragen gab, aber die meisten Antworten scheinen eher auf die Verschlüsselungsphilosophie als auf den eigentlichen Code zu verweisen.Symmetrisch verschlüsseln/entschlüsseln in .NET

Update: Ich würde wirklich gerne etwas Code sehen, anstatt nur Links. Danke vielmals!

+1

Ist Rijndael nicht symmetrisch? –

+0

Ich glaube, dass es –

+1

ist Ich würde Rijndael empfehlen, dann :) –

Antwort

11

Sehen Sie sich den Beispielcode am Ende von this page an.

Copy-Einfügen es hier:

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, mit dem nicht sicheren Random, um das Salz zu erstellen? Schlechte Idee. – blowdart

+6

@blowdart - Nein. Salz und IV müssen so einzigartig wie möglich sein, aber ihre sichere Erzeugung bedeutet nichts. Sicheres Zufällig bedeutet Zufall, das schwer vorherzusagen ist, und es ist dir egal, ob deine IV oder dein Salz vorhergesagt wird - sie werden sowieso im Klartext weitergegeben/gespeichert. – orip

+0

@blowdart - Ich räume deinen Punkt über IV im CBC-Modus ein. Es gilt jedoch nicht für Salz in PBKDF2. – orip

2

Konvertieren Sie Ihre Text, Schlüssel und Initialisierungsvektor zu Bytes, die zuerst die Codierung Ihrer Wahl verwenden. Dann nutzen Sie die Triple-DES-Anbieter, wie hier gezeigt:

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

oder den für AES, wenn Sie denken, Triple-DES ist zu der alten Schule, oder was auch immer.

Aus Neugier, wie planen Sie den geheimen Schlüssel zu kommunizieren?

+1

Sie versuchen also, Daten zu verschlüsseln, um den Benutzer daran zu hindern, sie zu lesen? –

+0

Für DES können der Schlüssel und IV irgendeine Zeichenkette sein, oder? –

+5

Das Codieren des Schlüssels in der Quelle einer .NET-Anwendung ist hoffnungslos unsicher. Der Benutzer muss lediglich den Reflektor herunterladen, und der Schlüssel befindet sich direkt vor Ort. –

5

Gut für Starter Tasten sind keine Zeichenfolgen, Schlüssel sind binäre Blobs. PlainText ist das gleiche, es ist nicht wirklich Text, auch hier ist es ein binärer Blob.

Jetzt können Sie natürlich Strings in Byte-Arrays mit Encoding.UTF8.GetBytes(message) konvertieren, jedoch beim Konvertieren von Schlüsseln hin und her ist es ein wenig komplizierter, verwenden Sie normalerweise Convert.ToBase64String und Convert.FromBase64String.

Vergessen Sie nicht, dass Blockchiffren der Initialisierungsvektor, auch noch etwas brauchen, also wirklich Ihre Methode Signaturen sollten

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

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

Der Schlüssel sein und IVs müssen kryptografisch sicheren Zufallszahlen, don sein‘ t geben Sie sie einfach ein und verwenden Sie nicht die Random-Funktion von C#. Die Größe des Schlüssels und der IV hängt vom verwendeten Verschlüsselungsalgorithmus ab und kann über die Eigenschaften der Klassen abgerufen werden.

generieren ein CSRPNG Sie etwas tun, wie

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

Sie auch die Rfc2898DeriveBytes Klasse verwenden kann, einen Schlüssel und IV von einem Passwort abgeleitet und ein Salz, aber auch hier das Salz sollte eine kryptografisch sichere Zufallszahl sein . Sie sollten auch beachten, wenn Sie einen symmetrischen Algorithmus erstellen einen sicheren Schlüssel und IV für Sie generiert wird.

Auf diese Weise können Sie dann die richtige Kodierung für Ihren Text wählen, sei es UTF8, ASCII oder was auch immer. Die Links haben genug Proben, so dass das Schneiden und Einfügen hier ziemlich sinnlos ist.

+1

Die IVs müssen nicht kryptographisch sicher sein, nur die Schlüssel. – orip

+1

Nicht wahr, im CBC-Modus muss die IV zum Zeitpunkt der Verschlüsselung unvorhersehbar sein – blowdart

+1

Danke, war mir dessen nicht bewusst. – orip

4

Hier ist eine einfache Lösung, die ich auf einem VB.NET Forum gefunden und in C# konvertiert. Es hat mir sicherlich geholfen, das Thema besser zu verstehen.

// 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()); 
    } 
}