Laden...

Stack Overflow beim Entschlüsseln

Erstellt von Philzstift vor 16 Jahren Letzter Beitrag vor 16 Jahren 2.081 Views
P
Philzstift Themenstarter:in
3 Beiträge seit 2007
vor 16 Jahren
Stack Overflow beim Entschlüsseln

Hi@all

wollte erstmal anmerken, das mir das Forum sehr gut gefällt. Echt Klasse!

Nun zu meinem Problem. Bin mal auf den Dreh gekommen so ne Art verschlüsselungsprogramm zu schreiben,d.h. ein benutzer meldet sich an, Name und Passwort werden in einer Datei verschlüsselt. bei der nächsten Anmeldung wird erkannt das der benutzer schon angelegt ist und es wird anch dem Passwort gefragt, wenn das Passwort stimmt gehts auch weiter. Allerdings kommt ein "Stack Overflow" wenn das Passwort nicht stimmt. Ist mir auch alles verständlich, nur suche ich eine Form, wie ich diesen fehler abfangen kann um dem benutzer quasi mitzuteilen das das Passwort falsch ist und vorallem das Programm nicht mit dem fehler beendet wird!?

Vielleicht könntet ihr mir mal einen guten Ansatz aufzeigen!

Danke,Phil

public static void Decrypt(string fileIn,
                string fileOut, string Password)
        {

            FileStream fsIn = new FileStream(fileIn,  //Ausgabe und Eingabe vertauschen
                        FileMode.Open, FileAccess.Read, FileShare.None);
            FileStream fsOut = new FileStream(fileOut,
                        FileMode.OpenOrCreate, FileAccess.Write, FileShare.None);  //FileShare sperrt den Vorgang für andere Zugriffe



            PasswordDeriveBytes pdb = new PasswordDeriveBytes(Password,
                new byte[] {0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 
            0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76});
            Rijndael alg = Rijndael.Create();

            alg.Key = pdb.GetBytes(32);
            alg.IV = pdb.GetBytes(16);


            CryptoStream cs = new CryptoStream(fsOut,
                alg.CreateDecryptor(), CryptoStreamMode.Write);
            

            int bufferLen = 4096;
            byte[] buffer = new byte[bufferLen];
            int bytesRead;

            do
            {
                bytesRead = fsIn.Read(buffer, 0, bufferLen);
                cs.Write(buffer, 0, bytesRead);

            } while (bytesRead != 0);
            
            cs.Close();     ----> STACK OVERFLOW
            fsIn.Close();
           
           
           
        }
49.485 Beiträge seit 2005
vor 16 Jahren

Hallo Philzstift,

cs.Close(); ----> STACK OVERFLOW

hm, ich kann mir nicht recht vorstellen, dass der StackOverflow durch das Close ausgelöst wird.

... wie ich diesen fehler abfangen kann ...

Ein StackOverflow kommt i.d.R durch ein Programmierfehler. Also sollte man den StackOverflow nicht abfangen, sondern durch Fehlerkorrektur vermeiden.

... um dem benutzer quasi mitzuteilen das das Passwort falsch ist.

Diese Fall sollte eigentlich einfacher sein, als der, wenn das Passwort stimmt.

herbivore

S
53 Beiträge seit 2006
vor 16 Jahren

Aus meiner Erfahrung kommt ien Stack Overflow zustanden wenn eine schleife unendlich läuft.
Daher die do..while schleife, ist die korrekt?
Ich bin ehrlich gesagt noch nicht ganz erfahren im Code aber so gesehen könnte der StackOverflow zustande kommen. Denn du prüfsst das verarbeitete byte ob es nicht null ist und nicht das nächste.

G
52 Beiträge seit 2007
vor 16 Jahren

Hi,
eine unentliche Schleife muss keine Stack-Overflow-Exception auslösen. Wie der Name des Fehlers bereits sagt, wird er ausgelöst, wenn der Stack überläuft. Dies geschieht oft und gerne bei Rekursionen, jedoch sehe ich in der Schleife keinen Grund für einen Overflow. Es wird ja nichts auf den Stack geschoben.

MfG,
Grouser.

S
53 Beiträge seit 2006
vor 16 Jahren

@Grouser

entschuldige, "kann unteranderem vorkommen" währen die richtigen Worte gewesen.

S
8.746 Beiträge seit 2005
vor 16 Jahren

Original von Speeedy
entschuldige, "kann unteranderem vorkommen" währen die richtigen Worte gewesen.

Nichtmal das. Der Stack wird nur in zwei Szenarien genutzt: Initialisierung eines lokalen Wertetypen (z.B. int) oder bei der Übergabe von Parametern auf dem Stack. Schleifen an sich können also nicht der Verursacher von Stackoverflows sein. Ersteres scheidet praktisch aus (wer definiert schon tausende von Variablen...). Bleibt also praktisch immer eine Rekursion als Ursache.

Ich würde mal den fin-Stream vor dem CryptoStream schließen und auch den Out-Stream zumachen.

P
Philzstift Themenstarter:in
3 Beiträge seit 2007
vor 16 Jahren

Guten Abend,

danke erstmal für die vielen Tips.

Habe erst das fsin.Close(); über den Cryptostream gesetzt, damit kamen allerdings neue Probleme. Man konnte somit nicht mehr auf die dadurch geschlossene Datei zugreifen. also "fsin.Close();" wieder ans Ende , dann noch das "fsOut.Close();" dazu und dann das cs.Close(); ausgeklammert und siehe da es läuft ohne Stack Overflow....habe alle Varianten durchprobiert, es schien doch an dem cs.Close(); gelegen zu haben!

public static void Decrypt(string fileIn,
                string fileOut, string Password)
        {
            
                FileStream fsIn = new FileStream(fileIn,  //Ausgabe und Eingabe vertauschen
                            FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
                FileStream fsOut = new FileStream(fileOut,
                            FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite);  //FileShare sperrt den Vorgang für andere Zugriffe



                PasswordDeriveBytes pdb = new PasswordDeriveBytes(Password,
                    new byte[] {0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 
                0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76});
                Rijndael alg = Rijndael.Create();

                alg.Key = pdb.GetBytes(32);
                alg.IV = pdb.GetBytes(16);

                
                CryptoStream cs = new CryptoStream(fsOut,
                    alg.CreateDecryptor(), CryptoStreamMode.Write);

                int bufferLen = 4096;
                byte[] buffer = new byte[bufferLen];
                int bytesRead;



                do
                {
                    bytesRead = fsIn.Read(buffer, 0, bufferLen);
                    cs.Write(buffer, 0, bytesRead);

                } while (bytesRead != 0);

                [B]fsIn.Close();
                fsOut.Close();[/B]
                
                
            }

Lg,Phil

183 Beiträge seit 2004
vor 16 Jahren

Hallo Philzstift,

dass du cs.Close() weglässt kann aber nicht die Lösung sein 🤔

Ich bin der Meinung, du hast den Algorithmus nicht vollständig Configuriert bzw. beachtest dessen Verhalten nicht ausreichend ...
Ich lass mich auch gern eines besseren belehren.

Bei mir kommt beim Close jedenfalls ne CryptographicException. Diese wird verursacht durch den übergebenen, zu verschlüsselnden Block deren Länge nicht mit der Blockgröße des Algorithmus übereinstimmt (Standard == 128 ). Außerdem füllst du den Block nicht mit den entsprechenden Füllzeichen (Standard == PCKS7) auf, wodurch der Algorithmus nicht richtig arbeiten kann.

Außerdem würd ich dir für Stream using ans Herz legen, dann vergisst du auch kein Close, Dispose oder Flush mehr 😉

Bei mir läuft folgendes ohne Probleme durch:

public static void Decrypt(string fileIn, string fileOut, string Password)
{
   using (FileStream fsIn = new FileStream(fileIn, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
   {
      using (FileStream fsOut = new FileStream(fileOut, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite))
      {
         PasswordDeriveBytes pdb = new PasswordDeriveBytes(Password, new byte[] {0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76});
         Rijndael alg = Rijndael.Create();

         alg.Key = pdb.GetBytes(32);
         alg.IV = pdb.GetBytes(16);
         alg.Padding = PaddingMode.Zeros; // Standard ist PKCS7

         using (CryptoStream cs = new CryptoStream(fsOut, alg.CreateDecryptor(), CryptoStreamMode.Write))
         {
            byte[] buffer = new byte[alg.BlockSize];
            int bytesRead = 0;
            do
            {
               bytesRead = fsIn.Read(buffer, 0, buffer.Length);

               //
               // Block mit 0 füllen
               // 
               if (bytesRead < buffer.Length)
               {
                  for (int i = bytesRead; i < buffer.Length; i++)
                     buffer[i] = 0;
               }

               if (bytesRead > 0)
                  cs.Write(buffer, 0, buffer.Length);

            } while (bytesRead > 0);
         }
      }
   }
}

Grüße él toro.

So einfach wie möglich, aber nicht einfacher. [Albert Einstein]

take a look at
* baer-torsten.de
* codinghints