Entwickler-Ecke

Basistechnologien - CryptoStream Exception "Zeichenabstände sind ungültig..."


C# - Sa 11.02.12 22:50
Titel: CryptoStream Exception "Zeichenabstände sind ungültig..."
Hey,

in meinem aktuellen Projekt möchte ich einen beliebigen String ver- und entschlüsseln. Das verschlüsseln klappt soweit auch gut.
Doch wenn ich dann wieder entschlüssle kommt beim byte 32 eine Fehlermeldung: "Zeichenabstände sind ungültig und können nicht entfernt werden.".
Ich habe mal gegoogelt und habe verschiedene Themen gefunden, wo steht, dass beim Verschlüsseln ungültige Unicode-Zeichen entstehen, die dann nicht entschlüsselt werden können.

Wie kann das sein?

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:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
static class Cryption
    {
        public enum CryptionBitMode { Bit128, Bit192, Bit256 }
        
        static public string Encrypt(string text, CryptionBitMode mode, byte[] key, byte[] iv)
        {
            int size;
            switch (mode)
            {
                case CryptionBitMode.Bit128: size = 128break;
                case CryptionBitMode.Bit192: size = 192break;
                case CryptionBitMode.Bit256: size = 256break;
                defaultthrow new Exception("Invalid CryptionBitMode.");
            }

            //Implementing a new Rijndael-instance
            Rijndael rijndael = Rijndael.Create();
            rijndael.BlockSize = size;
            rijndael.IV = iv;
            rijndael.Key = key;

            //Creating streams for cryption...
            MemoryStream stream = new MemoryStream();
            CryptoStream crypter = new CryptoStream(stream, rijndael.CreateEncryptor(), CryptoStreamMode.Write );

            //Encrypting string and write it to memory...
            byte[] buffer = Encoding.Unicode.GetBytes(text);
            crypter.Write(buffer, 0, buffer.Length);

            //Read the encrypted string form memory...
            buffer = new byte[stream.Length];
            stream.Seek(0, SeekOrigin.Begin);
            stream.Read(buffer, 0, buffer.Length);

            crypter.FlushFinalBlock();
            crypter.Close();
            stream.Close();

            //Return with the encrypted string...
            return Encoding.Unicode.GetString(buffer);
        }

        static public string Decrypt(string text, CryptionBitMode mode, byte[] key, byte[] iv)
        {
            int size;
            switch (mode)
            {
                case CryptionBitMode.Bit128: size = 128break;
                case CryptionBitMode.Bit192: size = 192break;
                case CryptionBitMode.Bit256: size = 256break;
                defaultthrow new Exception("Invalid CryptionBitMode.");
            }



            //Implementing a new Rijndael-instance
            Rijndael rijndael = Rijndael.Create();
            rijndael.BlockSize = size;
            rijndael.IV = iv;
            rijndael.Key = key;

            //Creating streams for cryption...
            MemoryStream stream = new MemoryStream();
            CryptoStream crypter = new CryptoStream(stream, rijndael.CreateDecryptor(), CryptoStreamMode.Read);

            //Write the encrypted text to memory
            byte[] buffer = Encoding.Unicode.GetBytes(text);
            stream.Write(buffer, 0, buffer.Length);

            //Read the encrypted stirng and decrypt it...
            buffer = new byte[stream.Length];
            stream.Seek(0, SeekOrigin.Begin);
            crypter.Read(buffer, 0, buffer.Length); //Hier tritt die Exception bei byte 32 auf
            
            crypter.FlushFinalBlock();
            crypter.Close();
            stream.Close();

            //Return with the encrypted string...
            return Encoding.Unicode.GetString(buffer);
        }
    }

An dieser Stelle wollte ich das ganze mal Testen und bin dann auf die Exception gestoßen.

C#-Quelltext
1:
2:
3:
4:
            byte[] key = encoder.GetBytes("TestingTheKey123"), IV = new byte[16]; //key erstellen
            for(int i = 0; i<IV.Length; i++) IV[i] = Convert.ToByte(i+5);             //IV erstellen
            string s = Cryption.Encrypt("Hallo Das hier ist Ein Test",Cryption.CryptionBitMode.Bit128, key, IV);
            string x = Cryption.Decrypt(s, Cryption.CryptionBitMode.Bit128, key, IV);

Was muss ich ändern oder was kann ich dagegen tun?

Hier der Crosspost im myCSharp-Forum [http://www.mycsharp.de/wbb2/thread.php?threadid=101601]


Th69 - So 12.02.12 11:23

Hallo C#,

was mir sehr eigenartig erscheint, ist, daß du die verschlüsselten Daten als String wieder zurückgibst, um sie dann der Decrypt-Methode als Eingabeparameter zu geben.
Probiere mal einfach das byte-Array zurückzugeben und direkt auf diesem Array zu entschlüsseln.

Du hast ja sonst zu viele umständliche Konvertierungen drin (und nicht jeder beliebige Byte-Stream ist ein gültiges Unicode-Format)...

P.S. Bitte Cross-Posts immer angeben: myCSharp.de - CryptoStream Exception "Zeichenabstände sind ungültig..." [http://www.mycsharp.de/wbb2/thread.php?goto=lastpost&threadid=101601]


C# - So 12.02.12 13:03

Danke für die Hilfe, funktioniert aber trotzdem nicht... ich habe es auch schon mit Base64String probiert aber des geht auch nicht. Hat noch jemand eine Idee?


C# - So 12.02.12 14:45

Also ich hab die Lösung: Wenn ich cryptor.FlushFinalBlock() direkt hinter den letzten Schreibvorgang bei der Encrypt-Methode setzte funktioniert alles wie es soll.


C# - Mo 13.02.12 15:48

Also ich dreh jetzt dann am Rad.
Wenn ich jetzt die Encrypt und danach die Decrypt Methode aufrufe klappt alles wie es soll.
Doch wenn ich jetzt Encrypte und die Bytes übers Netzwerk an nen anderen pc sende und dort dann wieder Decrypter, kommt wieder die gleiche Fehlermeldung.
Woran zum Teufel liegt das? Ich werd hier gleich irre :autsch:

Im Anhang findet ihr die komplette Klasse für die Verschlüsselung.

Bitte helft mir...


C# - Mo 13.02.12 21:47

So. aber jetzt hab ich den Fehler selbst gefunden. Und jetzt funktioniert es auch wirklich.
Ich hab nicht die überschüssigen NullBytes am ende des Puffers entfernt, also die Puffergröße angepasst.

Jetzt klappt alles wie es soll.