mit Rijndael und Cryptostream richtig entschlüsseln

Azraelgod

Grünschnabel
PHP:
 if(schlDateiNeu == true)
   {
	generateAES(passwd);
	generateRSA();
	FileStream fsschl = new FileStream(schlDatei.FullName, FileMode.Create, FileAccess.ReadWrite, FileShare.None);
	byte[] b = new byte[1];
	b[0] = Convert.ToByte(salt.Length);
	fsschl.Write(b, 0, b.Length);
	b = ASCIIEncoding.ASCII.GetBytes(salt);
	fsschl.Write(b, 0, b.Length);
	b = new byte[symCrypt.IV.Length];
	fsschl.Write(b,0,b.Length);
	ICryptoTransform transform = symCrypt.CreateEncryptor(); 
	CryptoStream cryptStream = new CryptoStream(fsschl, transform,CryptoStreamMode.Write);
	b = ASCIIEncoding.ASCII.GetBytes(asymCrypt.ToXmlString(true));
	cryptStream.Write(b,0,b.Length);
	cryptStream.FlushFinalBlock();
	fsschl.Close();
   }
   else
   {
	FileStream fsschl = new FileStream(schlDatei.FullName, FileMode.Open, FileAccess.ReadWrite, FileShare.None);
	symCrypt = new RijndaelManaged();
	byte[] b = new byte[1];
	fsschl.Read(b, 0, b.Length);
	b = new byte[Convert.ToInt32(b[0])];
	fsschl.Read(b,0,b.Length);
	salt = ASCIIEncoding.ASCII.GetString(b);
	b = new byte[16];
	fsschl.Read(b,0,b.Length);
	symCrypt.IV = b;
	String saltedPass = "";
	for(int i = 0, j = 0; i < passwd.Length || j < salt.Length; i++, j++)
	{
	 if(i < passwd.Length)
	  saltedPass = saltedPass + passwd.ToCharArray()[i];
	 if(j < salt.Length)
	  saltedPass = saltedPass + salt.ToCharArray()[j];
	}
	symCrypt.Key = ASCIIEncoding.ASCII.GetBytes(saltedPass);

	ICryptoTransform transform = symCrypt.CreateDecryptor();
	CryptoStream cryptStream = new CryptoStream(fsschl, transform, CryptoStreamMode.Read);
	String temp = "";
	b = new byte[schlDatei.Length - fsschl.Position];
	try
	{
	 cryptStream.Read(b,0,b.Length);
	 temp = ASCIIEncoding.ASCII.GetString(b, 0, b.Length);	 
	}
	catch(Exception ex)
	{
	 System.Console.Out.WriteLine(ex);
	}
	  
	fsschl.Close();

symCrypt ist eine Instanz von RijndaelManaged und asymCrypt von RSACryptoServiceProvider, dessen Daten ich verschlüsseln will. Die erste Hälfte der if-Schleife verschlüsselt die Daten, die 2. entschlüsselt sie.
Das Passwort wird mit einem zufälligen Salt verschlüsselt. Das Abspeichern geht folgendermaßen vor sich: [Länge des Salt][Salt][Rijndael.IV][Daten]
Es klappt auch (fast) alles und ich bekomme auch einen Großteil meiner verschlüsselten Daten wieder, allerdings ist der Anfang des entschlüsselten Textes immer nur Mist (10-15 Zeichen Buchstabensalat)

Wenn irgendjemand eine Idee hat, wäre ich sehr froh (hänge da jetzt schon 6 Stunden dran).

Azraelgod
 
Der von dir beschriebene Buchstabensalat am Anfang entsteht meist durch einen
fehlerhaften Initialisierungsvektor.
Ein Fehler liegt sicherlich in dieser Zeile: (bei der Verschlüsselung)
Code:
b = new byte[symCrypt.IV.Length];
fsschl.Write(b,0,b.Length);
Hier schreibst du ein leeres byte-array mit der Länge "symCrypt.IV.Length" in die
Datei und versuchst später daraus den Initialisierungsvektor zu generieren.
(Was natürlich fehlschlägt)

Bessere das mal aus und probier es erneut.
Den Rest des Codes hab ich nur überflogen. Wenn noch was ist, melde dich nochmal.
 
Nein, der Initialisierungsvektor ist nicht leer, da ich mit den Methoden generateAES(passwd); und generateRSA(); symCrypt und asymCrypt initialisiere. Ich habe sowohl den ausgelesenen Salt, als auch den Vektor verglichen, beide sind identisch. Nach den ersten 10-15 Zeichen Buchstabensalat (der eigentlich der xml-header vom rsa-export sein sollte), sind die Zeichen ja in Ordnung, d.h. dort stimmen dann auch wieder die xml-tags.
Beim Debuggen habe ich festgestellt, daß beim Lesen 1 Byte mehr genommen wird, als beim Schreiben ursprünglich mit übergeben wird. Dieses extra Byte kommt vom flushfinalblock(). Ich kann es aber auch nicht abschneiden, da sonst die Blocklänge für den Rijndael-Algorithums nicht mehr stimmt.
 
ich meinte auch nicht das der Initialisierungsvektor leer ist, sondern dass du statt des
Initialisierungsvektors ein leeres byte-array (also eine Folge von null-Werten) in die Datei schreibst:

Code:
// neues byte-array mit der Länge "symCrypt.IV.Length" erzeugt.
b = new byte[symCrypt.IV.Length];

// keine weitere Zuweisung von b, das heisst b ist immer noch leer

// schreiben von b in die Datei
fsschl.Write(b,0,b.Length);

oder erfüllt das leere byte-array einen anderen Zweck ?
 
Danke, das war das Ei des Kolumbus!
Wenn man selbst davor sitzt, dann erkennt man solche Fehler selten. Funktioniert jetzt wunderbar
Danke nochmal :)
 

Neue Beiträge

Zurück