Autor Beitrag
Flitzs
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 123
Erhaltene Danke: 7

Win7 x64/86 WinServer 2008 R2 x64
C#/C++/C VS2010
BeitragVerfasst: Mi 13.01.10 22:34 
Hallo,

vorab, ich benütze .Net 4.0, doch diese Version ist in der Combo Box weiter oben nicht auswählbar.

Ich habe eine Frage zur verschlüsselungen/entschlüsselung mithilfe der AesCryptoServiceProvider Klasse:

Zur besseren Verständnis des Codes der noch folgt, hier eine Klasse die ich benütze, um die Daten für die AES ver-/entschlüsselung zu halten.
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
 public class AESEncryptionSettings : IDisposable
    {        
        public byte[] Key { get; set; }       
        public byte[] IV { get; set; }      
        public ICryptoTransform Encrypter { get; set; }       
        public ICryptoTransform Decrypter { get; set; }
    }

(IDisposable wird weiter unten implementiert, ist hier aber nicht wichtig)

Ich habe mir folgende Funktion geschrieben, um den Schlüssel und co. zu generieren.

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
 public const int AESKeyLength = 256;
 public static AESEncryptionSettings GenerateAESSettings(byte[] ivToUse = nullbyte[] keyToUse = null)
        {
            AESEncryptionSettings AESSettings = new AESEncryptionSettings();

            AesCryptoServiceProvider acp = new AesCryptoServiceProvider();
            acp.BlockSize = 128;
            acp.KeySize = AESKeyLength;
            if (ivToUse == null)
                acp.GenerateIV();
            else
                acp.IV = ivToUse;
                            
            if (keyToUse == null)
                acp.GenerateKey();
            else
                acp.Key = keyToUse;

            AESSettings.IV = acp.IV;
            AESSettings.Key = acp.Key;
            AESSettings.Decrypter = acp.CreateDecryptor();
            AESSettings.Encrypter = acp.CreateEncryptor();
            acp.Dispose();                                                

            return AESSettings;
        }


Die Frage ist nun, wie entschlüssle/verschlüssle ich die Daten nun?

Eine Nachricht zu ent-/verschlüsseln ist noch relativ einfach
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
        
        public static byte[] EncryptAES(byte[] plain, AESEncryptionSettings settings)
        {
            return settings.Encrypter.TransformFinalBlock(plain, 0, plain.Length);
        }      
        public static byte[] DecryptAES(byte[] encrypted, AESEncryptionSettings settings)
        {           
            return settings.Decrypter.TransformFinalBlock(encrypted, 0, encrypted.Length);
        }


Doch was nun, wenn ich mehrere Nachrichten hintereiander ver-/entschlüsseln möchte?
Zwar gibt es die ICryptoTransform.TransformBlock Methode die wohl dafür gedacht ist, doch benötige ich hierfür die Länge der Ausgangsnachricht, die ich nicht kenne.
Ist das so dann nicht implementierbar? Bzw ist AES dafür nicht gedacht? Was gibt es für Alternativen?

mfg Flitzs

EDIT: Versuche ich damit, mehrere Nachrichten zu ent-/verschlüsselen, wird beim zweiten entschlüsseln eine System.Security.Cryptography.CryptographicException mit der Meldung: "Padding is invalid and cannot be removed." ausgelöst.
Flitzs Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 123
Erhaltene Danke: 7

Win7 x64/86 WinServer 2008 R2 x64
C#/C++/C VS2010
BeitragVerfasst: Mi 13.01.10 23:11 
Hi,

hier ein paar Änderungen die ich gemacht habe:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
       public static byte[] EncryptAES(byte[] plain, AESEncryptionSettings settings)
        {
            byte[] result;
            using (MemoryStream inputStream = new MemoryStream())
            {
                using (CryptoStream cStream = new CryptoStream(inputStream, settings.Encrypter, CryptoStreamMode.Write))
                    cStream.Write(plain, 0, plain.Length);
                result = inputStream.ToArray();
            }

            return result;          
        }       
        public static byte[] DecryptAES(byte[] encrypted, AESEncryptionSettings settings)
        {
            byte[] result;
            using (MemoryStream inputStream = new MemoryStream())
            {
                using (CryptoStream cStream = new CryptoStream(inputStream, settings.Decrypter, CryptoStreamMode.Write))
                    cStream.Write(encrypted, 0, encrypted.Length);
                result = inputStream.ToArray();
            }
            return result;            
        }


Den Fehler der vorher kahm, konnte ich damit elemieren, indem ich die Nachrichten mindestens 16 Byte (also die Blocklänge) lang gemacht habe.

Doch kommt beim 2ten Entschlüsseln nur noch Müll heraus. Muss ich mir die Instanzen von ICrypoTransform jedes mal neu erzeugen (mithilfe des Keys und IVs)?

mfg Flitzs
Kha
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: Do 14.01.10 01:00 
Kenne mich im Crypto-Bereich nicht aus, aber so, wie es aussieht, musst du wohl wirklich acp.CreateEn/Decryptor jedes Mal neu aufrufen.

PS: Deine Methode GenerateAESSettings nennt man landläufig auch "Konstruktor" :mrgreen: .

_________________
>λ=
Flitzs Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 123
Erhaltene Danke: 7

Win7 x64/86 WinServer 2008 R2 x64
C#/C++/C VS2010
BeitragVerfasst: Do 14.01.10 11:18 
Hi,

ein Konstruktor wäre es doch nur, wenn die Klasse/Methode nicht statisch wäre. Sinn dahinter ist, dass ich mehrer Verschlüsselungsalgorithmen in einer statischen Klasse habe.

mfg Flitzs
Kha
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: Do 14.01.10 21:36 
user profile iconFlitzs hat folgendes geschrieben Zum zitierten Posting springen:
ein Konstruktor wäre es doch nur, wenn die Klasse/Methode nicht statisch wäre.
Ein Konstruktor ist im Grunde eine statische Methode.
Mein "PS" sollte einfach ein Wink mit dem Zaunpfahl sein, dass diese Methode ein Konstruktor sein sollte... ;)

_________________
>λ=
Flitzs Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 123
Erhaltene Danke: 7

Win7 x64/86 WinServer 2008 R2 x64
C#/C++/C VS2010
BeitragVerfasst: Do 14.01.10 22:18 
Hey,

die Funktionen Encrypt/DecryptAES und GenerateAESSettings sind Teil einer statischen Klasse, die mehrer solche Funktionen für verschiedene Verschlüsselungsalgorithmen bereitstellt.

mfg Flitzs