Bei Visual Studio: Breakpoint bei "Reader.Close()" setzen (Die Exception wird vermutlich erst danach geworfen). Entweder durch klicken auf die graue Spalte links neben der Codezeile oder mit F9. Dann das Programm im Debug-Modus starten (F5). Wenn der Breakpoint erreicht wird, kannst du mit F10 zeilenweise durch den Code durchgehen.
Du verwendest einen veralteten Browser. Es ist möglich, dass diese oder andere Websites nicht korrekt angezeigt werden.
Du solltest ein Upgrade durchführen oder einen alternativen Browser verwenden.
Du solltest ein Upgrade durchführen oder einen alternativen Browser verwenden.
C# WPF RichTextBox: Wie komm ich an den formatierten Text?
- Ersteller UID0
- Erstellt am
- Registriert
- Juli 2010
- Beiträge
- 1.050
OK, werd ich versuchen.
Ich habe das ganze jetzt mal wieder mit kleineren Dateien ausprobiert. Da funktioniert es anstandslos. Jedoch habe ich bei großen Dateien immer noch das Problem und es wird wieder ein OutofMemory Fehler ausgespuckt. Demnach liegt es daran, dass der String zu groß wird.
das mit dem Debuggen hat mir auch nicht viel mehr aufgezeigt.
Der Stringbuilder schaut bei der großen Datei so aus:
und bei der kleinen Datei so:
Also gleich. Jedoch funktioniert alles bei der kleinen Datei. Auch die verschlüsselten Dateien lassen sich öffnen. Nur bei der Großen nicht.
Achso, der decoded string bleibt auch leer.
Ergänzung ()
Ich habe das ganze jetzt mal wieder mit kleineren Dateien ausprobiert. Da funktioniert es anstandslos. Jedoch habe ich bei großen Dateien immer noch das Problem und es wird wieder ein OutofMemory Fehler ausgespuckt. Demnach liegt es daran, dass der String zu groß wird.
das mit dem Debuggen hat mir auch nicht viel mehr aufgezeigt.
Der Stringbuilder schaut bei der großen Datei so aus:
Code:
{<FlowDocument PagePadding="5,0,5,0" AllowDrop="True" NumberSubstitution.CultureSource="User" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"><Paragraph><Run xml:lang="de-de">123</Run></Paragraph></FlowDocument>+*+++~##EEAD by Chriss000xx.sssd-#+++:8BPS}
und bei der kleinen Datei so:
Code:
{<FlowDocument PagePadding="5,0,5,0" AllowDrop="True" NumberSubstitution.CultureSource="User" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"><Paragraph><Run xml:lang="de-de">123</Run></Paragraph></FlowDocument>+*+++~##EEAD by Chriss000xx.sssd-#+++:8BPS}
Also gleich. Jedoch funktioniert alles bei der kleinen Datei. Auch die verschlüsselten Dateien lassen sich öffnen. Nur bei der Großen nicht.
Achso, der decoded string bleibt auch leer.
Zuletzt bearbeitet:
Wenn der String zu lang wird, muss du eben häppchenweise decodieren. Da du mehrere Dateien in eine Datei verschlüsselst wird's etwas komplizierter. Du könntest z.B. einen Header einfügen, der die Dateinamen und -Länge enthält, d.h. du weißt, wo du trennen musst. Die ersten 4 Bytes könnten dann die Länge des Headers selbst angeben, damit du weißt, wo der aufhört.
Dass hat dann den Vorteil, dass du nicht die komplett decodierte Datei auf einmal im Speicher hast, und es fallen auch keine teuren String-Operationen (insbesondere das zig-fache Split) mehr an.
Dass hat dann den Vorteil, dass du nicht die komplett decodierte Datei auf einmal im Speicher hast, und es fallen auch keine teuren String-Operationen (insbesondere das zig-fache Split) mehr an.
Du weist doch, welche und wie viele Dateien du verschlüsselst. Damit kannst du die Headergröße berechnen.
Alternativ kannst du die Informationen auch so speichern:
[Länge der Datei 1]
[Länge des Dateinames]
[Dateiname]
[Dateiinhalt]
[Länge der Datei 2]
...
Und das für jede Datei.
Alternativ kannst du die Informationen auch so speichern:
[Länge der Datei 1]
[Länge des Dateinames]
[Dateiname]
[Dateiinhalt]
[Länge der Datei 2]
...
Und das für jede Datei.
Chriss000 schrieb:Nein, weiß ich nicht. Das Programm soll auf beliebig viele und große Dateien anwendbar sein.
Doch weißt du
Ein etwas ausführlicheres Beispiel:
Du speicherst alle Dateien in einem Container.
Was du nun tun kannst ist folgendes:
Wenn du den Container anlegst, schreibst du einen Header rein, bevor du überhaupt irgendwas anderes reinschreibst.
z.B.:
4 byte deiner Wahl, an denen du deinen Container identifizieren kannst.
32 byte für einen Password Hash, damit kannst du am beim Laden des Containers direkt prüfen, ob der jenige, der ihn läd, auch was damit anfangen kann. Nur einen Hash, nicht das PW mit dem du die Dateien verschlüsselt hast.
Ab jetzt fängst du an die Dateien reinzuschreiben.
Allerdings schreibst du für jede Datei wieder einen Header.
Zuerst:
8 byte für die Länge der Datei (sizeof(long))
512 byte für den Dateinamen. Klingt viel, brauchst du aber. Windows unterstützt 256 Zeichen für eine Datei. Ich empfehle dir hier eine UTF16 Encodierung wegen der konstanten Länge.
Nun schreibst du die eigentliche Datei in den Container.
Für jede weitere Datei machst du genau das Gleiche. Erst die Länge, dann den Namen, dann die Daten.
Das ganze würde für 3 Dateien so aussehen:
4B + 32B + 8B + 512B + xB + 8B + 512B + xB + 8B + 512B + xB.
Beim öffnen deines Containers musst du dann nicht erst alles lesen, bevor du irgendwas über den Inhalt sagen kannst. Mit diesen Header könntest du auch eine bestimmte Datei wieder Entschlüsseln ohne vorher den ganzen Container zu bearbeiten.
Zu deinem Problem mit der OutOfMemoryException.
Du liest den ganzen Container, das ist offensichtlich zu viel. Was du tun kannst, ist einen Buffer von z.B. 4kB Größe zu verwenden. D.h. du liest immer nur 4kB aus dem Container und übergibst sie dem CryptStream, dann wieder 4kB usw. bis du alles gelesen hast.
- Registriert
- Juli 2010
- Beiträge
- 1.050
Achso. Jetzt hab ich verstanden. Danke, werd ich versuchen.
@Darlis: Sry, hab ich überlesen.
EDIT: Gibt es nicht noch irgendeine andere Möglichkeit. Müsste jetzt nämlich mein kompletten Programm umschreiben.
Kann man nicht mit Virtuellen Laufwerken arbeiten? Aber nicht so wie Truecrypt. Sondern nur für das Programm.
Oder gibt es irgendeinen Datentyp, der extra für sowas gemacht ist? Wie wärs, dass man komplett mit Byte[]s arbeitet. Funktioniert das, oder erhalte ich da auch einen OutOfMemory Fehler?
@Darlis: Sry, hab ich überlesen.
EDIT: Gibt es nicht noch irgendeine andere Möglichkeit. Müsste jetzt nämlich mein kompletten Programm umschreiben.
Kann man nicht mit Virtuellen Laufwerken arbeiten? Aber nicht so wie Truecrypt. Sondern nur für das Programm.
Oder gibt es irgendeinen Datentyp, der extra für sowas gemacht ist? Wie wärs, dass man komplett mit Byte[]s arbeitet. Funktioniert das, oder erhalte ich da auch einen OutOfMemory Fehler?
Zuletzt bearbeitet:
Du möchtest beliebig viele und beliebig große Dateien ver- und entschlüsseln, dabei aber alle Daten im Speicher vorhalten. Auch wenn du auf String-Operationen verzichtest, wirst du früher oder später die nächste OutOfMemoryException bekommen. Also ja, du musst das Programm überarbeiten.
Was soll den mit den entschlüsselten Dateien passieren? Warum müssen die Daten im Speicher bleiben?
Was soll den mit den entschlüsselten Dateien passieren? Warum müssen die Daten im Speicher bleiben?
Ich denke nicht, da Rijndahl ein Blockchiffre ist. Die Anzahl der Bytes in der verschlüsselten Datei ineterssieren dich aber nicht, da du die Datei vor dem verabeiten ja wieder entschlüsselst. Also etwa so:
Code:
FileStream file = new FileStream(path, FileMode.Open);
cstream = new CryptoStream(file, _rijndael.CreateDecryptor(_rijndael.Key, _rijndael.IV), CryptoStreamMode.Read);
/* 4 Byte ID lesen und prüfen, ob es sich um unseren Container handelt */
Byte[] containerId = new Byte[4];
cstream.Read(containerId, 0, 4)
/* 32 Byte Passwort-Hash lesen um das Passwort zu prüfen */
Byte[] pwHash= new Byte[32];
cstream.Read(pwHash, 0, 32)
Zuletzt bearbeitet:
- Registriert
- Juli 2010
- Beiträge
- 1.050
Ich glaub ich steh gerad aufm Schlauch. Der Header wird doch so aufgebaut:
Bei den Rot markierten Stellen weiß ich nun nicht, wie ich das hin bekomme, da ich ja den Header eigentlich erst nach der Verschlüsslung schreiben kann, da ich erst dann die Positionen bestimmen kann.
id (4b) + hash(32b) + LängedesFlowDoc(16b) + FlowDoc(?b)
+ AnzahlderDateien(10b)
+Datei1Name(256b)
+Datei1Anfangsposition(32b) //Gibt an wo "Datei1Data" beginnt
+Datei1Endposition(32b) /Gibt an wo "Datei1Data" endet
+Datei2Name(256b)
+Datei2Anfangsposition(32b)
+Datei2Endposition(32b)
usw.
+ Datei1Data + Datei2Data usw.
Bei den Rot markierten Stellen weiß ich nun nicht, wie ich das hin bekomme, da ich ja den Header eigentlich erst nach der Verschlüsslung schreiben kann, da ich erst dann die Positionen bestimmen kann.
TheCadillacMan
Captain
- Registriert
- Juni 2005
- Beiträge
- 3.188
Du kennst doch die Reihenfolge und die Länge der Dateien also kannst du dir die Positionen berechnen. Die verschlüsselten Positionen interessieren dich nicht, da der CryptoStream eh entschlüsselt liest.
Die Anfangsposition ist doch immer die Endpositon der letzten Datei + Länge des Dateinamen + 1.
Die Endposition ist Anfang + Länge des Inhalts.
Die Anfangsposition ist doch immer die Endpositon der letzten Datei + Länge des Dateinamen + 1.
Die Endposition ist Anfang + Länge des Inhalts.
Der Dateiname steht ja im Header, also ist die Anfangposition nur die Endpositon der letzten Datei + 1.TheCadillacMan schrieb:Die Anfangsposition ist doch immer die Endpositon der letzten Datei + Länge des Dateinamen + 1.
@Chriss000: Speicher lieber die Länge der Datei, nicht die Endposition, sonst kommst du noch in Versuchung, die Datei wieder komplett einzulesen
Die Größen, die du verwendest sehen etwas komisch aus. 256 Bit für einen Dateinamen ist viel zu wenig, 32 Byte für eine Dateigröße ist erheblich zu viel. Mit 8 Byte kommst du schon auf 16 Mio. Terrabyte.
TheCadillacMan
Captain
- Registriert
- Juni 2005
- Beiträge
- 3.188
Stimmt natürlich. Ich hab oben den Header mit dem Inhalt irgendwie durcheinander gebracht.Darlis schrieb:Der Dateiname steht ja im Header, also ist die Anfangposition nur die Endpositon der letzten Datei + 1.
- Registriert
- Juli 2010
- Beiträge
- 1.050
Sry, Ich meinte eigentlich 256 Bytes nicht Bits.Die Größen, die du verwendest sehen etwas komisch aus. 256 Bit für einen Dateinamen ist viel zu wenig, 32 Byte für eine Dateigröße ist erheblich zu viel. Mit 8 Byte kommst du schon auf 16 Mio. Terrabyte.
Ergänzung ()
Heute Abend habe ich keine Zeit mehr. Leider. Mal sehen, ob ich morgen Zeit finde.