Free Pascal Compiler - Stream read error
Hallo Alle und Moinsen
System:
Windows 7, x64
Free Pascal Compiler 3.0.4
Lazarus IDE 1.8.4
In der Hoffnung, hier noch einen weisen Pascal-Coder zu finden:
Ich habe ein kleines Konsolen-Programm geschrieben, das kurze Texte entgegen nimmt, verschlüsselt (BlowFish) und in eine Datei schreibt. Zudem kann der Datei-Inhalt zurückgelesen, entschlüsselt und in der Konsole angezeigt werden.
Zum Speichern/Laden nutze ich Streams (TStringStream).
Die Verschlüsselung funktioniert perfekt.
Die Entschlüsselung aber nur, wenn der String exakt 4 Zeichen lang ist. Sonst schmeißt es folgenden Fehler:
Mein erster Gedanke war ein Zeichensatz-Problem beim Übergang Console/Stream. Aber dann sollten mMn auch die 4-Zeichen-Strings denselben Fehler schmeißen - tun sie aber nicht. Ich habe eine Reihe von 4-Zeichen-Kombinationen durchgespielt - werden korrekt ver-/entschlüsselt.
Habe mittlerweile dutzende von Artikeln gelesen, Foren durchstöbert und Zeichensatz-Umwandlungen probiert, aber keine Erleuchtung zu vermelden.
Am BlowFish-Algorithmus liegt es auch nicht, der funktioniert perfekt (habe ich mit einer kleinen Test-Routine nachvollziehen können). Das explizite Setzen der CodePage in der Console bringt ebenfalls nix. Ich bin schlussendlich auf die Schnappsidee gekommen, die ASCII/ANSI-Codes der Chiffre in die Datei zu schreiben - ooch nöscht.
Mein Schädel stößt bereits kleine Rauchwolken aus ... ich hoffe, die Krankenkasse übernimmt das (btw: bitte keine anzüglichen Wortspiele mit dem Crypto-Algorithmus!).
Kennt einer von euch da draußen an den Geräten dieses Phänomen? Kann es mir jemand erklären? Hat jemand eine Lösung / einen Lösungsansatz?
Gruß und schöne Adzwenzzeit euch allen
Ankh
Hier noch der Quelltext:
System:
Windows 7, x64
Free Pascal Compiler 3.0.4
Lazarus IDE 1.8.4
In der Hoffnung, hier noch einen weisen Pascal-Coder zu finden:
Ich habe ein kleines Konsolen-Programm geschrieben, das kurze Texte entgegen nimmt, verschlüsselt (BlowFish) und in eine Datei schreibt. Zudem kann der Datei-Inhalt zurückgelesen, entschlüsselt und in der Konsole angezeigt werden.
Zum Speichern/Laden nutze ich Streams (TStringStream).
Die Verschlüsselung funktioniert perfekt.
Die Entschlüsselung aber nur, wenn der String exakt 4 Zeichen lang ist. Sonst schmeißt es folgenden Fehler:
Project crypt hat Exception-Klasse "EReadError" ausgelöst mit der Meldung:
Stream read error
Bei Adresse 410EE5
Mein erster Gedanke war ein Zeichensatz-Problem beim Übergang Console/Stream. Aber dann sollten mMn auch die 4-Zeichen-Strings denselben Fehler schmeißen - tun sie aber nicht. Ich habe eine Reihe von 4-Zeichen-Kombinationen durchgespielt - werden korrekt ver-/entschlüsselt.
Habe mittlerweile dutzende von Artikeln gelesen, Foren durchstöbert und Zeichensatz-Umwandlungen probiert, aber keine Erleuchtung zu vermelden.
Am BlowFish-Algorithmus liegt es auch nicht, der funktioniert perfekt (habe ich mit einer kleinen Test-Routine nachvollziehen können). Das explizite Setzen der CodePage in der Console bringt ebenfalls nix. Ich bin schlussendlich auf die Schnappsidee gekommen, die ASCII/ANSI-Codes der Chiffre in die Datei zu schreiben - ooch nöscht.
Mein Schädel stößt bereits kleine Rauchwolken aus ... ich hoffe, die Krankenkasse übernimmt das (btw: bitte keine anzüglichen Wortspiele mit dem Crypto-Algorithmus!).
Kennt einer von euch da draußen an den Geräten dieses Phänomen? Kann es mir jemand erklären? Hat jemand eine Lösung / einen Lösungsansatz?
Gruß und schöne Adzwenzzeit euch allen
Ankh
Hier noch der Quelltext:
Program crypt;
{$mode objfpc}{$H+}
uses
Classes, Crt, SysUtils, BlowFish;
const TheFile: String = 'CryptFile.txt';
var
EncodeBlowFishStream: TBlowFishEncryptStream;
DecodeBlowFishStream: TBlowFishDeCryptStream;
EncodeStringStream,DeCodeStringStream: TStringStream;
EncodeString,DecodedString,key,value: String;
Choice: Char;
Procedure Encrypt;
Begin
EncodeStringStream := TStringStream.Create('');
EncodeBlowFishStream := TBlowFishEncryptStream.Create(key,EncodeStringStream);
EncodeBlowFishStream.WriteAnsiString(value);
EncodeString := EncodeStringStream.DataString;
EncodeBlowFishStream.Free;
EncodeStringStream.Free;
End;
Procedure Decrypt;
Begin
DeCodeStringStream := TStringStream.Create(value);
DecodeBlowFishStream := TBlowFishDeCryptStream.Create(key,DeCodeStringStream);
DecodedString := DecodeBlowFishStream.ReadAnsiString;
DecodeBlowFishStream.Free;
DeCodeStringStream.Free;
End;
Function ReadFile(File2Read:String):String;
Var String2Read: TstringList;
Begin
Value:='';
String2Read := TStringList.Create;
Try
String2Read.LoadFromFile(File2Read);
value:=String2Read;
Finally
String2Read.Free;
End;
End;
Function WriteFile(File2Write:String):String;
Var String2Write: TStringList;
Begin
String2Write := TStringList.Create;
Try
String2Write.Add(EncodeString);
String2Write.SaveToFile(File2Write);
Finally
String2Write.Free;
EncodeString:='';
End;
End;
Begin
While True Do
Begin
ClrScr;
TextColor(LightGreen);
Write('Encrypt = 1 | Decrypt = 2 | Exit = 3 ... Your choice: ');
Choice := ReadKey;
WriteLn;
If Choice='3' Then
Halt(0);
Write('Key: ');
ReadLn(key);
Case Choice of
'1': Begin
Write('Text: ');
ReadLn(value);
Encrypt;
WriteLn('Encrypted: ' + EncodeString);
WriteLn('Decrypted: ' + value);
WriteFile(TheFile);
End;
'2': Begin
ReadFile(TheFile);
Decrypt;
WriteLn('Encrypted: ' + value);
writeLn('Decrypted: ' + DecodedString);
End;
End; //Case
WriteLn;
TextColor(white);
Write('Press ENTER to continue...');
ReadLn;
End; //While
End.
Bitte markiere auch die Kommentare, die zur Lösung des Beitrags beigetragen haben
Content-ID: 394842
Url: https://administrator.de/contentid/394842
Ausgedruckt am: 22.11.2024 um 15:11 Uhr
11 Kommentare
Neuester Kommentar
Moin.
Wo liegt die zu lesende Datei? Auf einem Netzlaufwerk?
Gruß A.
Wo liegt die zu lesende Datei? Auf einem Netzlaufwerk?
Gruß A.
OK, ich bau die Build-Umgebung nachher mal in einer VM nach und gebe Rückmeldung was dein Code dort meldet.
'n Abend Ankh,
ich bin Delphi-Entwickler und kenne deshalb die Details der FPC RTL nicht. Die Doku von ReadAnsiString sagt jedoch:
Das mit den 4 Bytes kommt mir schonmal verdächtig vor. Was passiert, wenn Du die Prozedur Decrypt folgendermaßen umschreibst:
Grüße
Friemler
ich bin Delphi-Entwickler und kenne deshalb die Details der FPC RTL nicht. Die Doku von ReadAnsiString sagt jedoch:
The Ansistring should be stored as 4 bytes (a DWord) representing the length of the string, and then the string value itself. The WriteAnsiString function writes an ansistring in such a format.
Das mit den 4 Bytes kommt mir schonmal verdächtig vor. Was passiert, wenn Du die Prozedur Decrypt folgendermaßen umschreibst:
Procedure Decrypt;
var
TmpStream: TStringStream;
Begin
DeCodeStringStream := TStringStream.Create(value);
DecodeBlowFishStream := TBlowFishDeCryptStream.Create(key,DeCodeStringStream);
TmpStream := TStringStream.Create('');
TmpStream.CopyFrom(DecodeBlowFishStream, DecodeBlowFishStream.Size);
DecodedString := TmpStream.DataString;
TmpStream.Free;
DecodeBlowFishStream.Free;
DeCodeStringStream.Free;
End;
Grüße
Friemler
Moin Ankh,
die Länge des BlowFish-Streams wird intern anscheinend durch eine Suchoperation bestimmt. Kann die Längenangabe (Parameter 2) der CopyFrom-Methode wie in Delphi auf 0 gesetzt werden, um den gesamten Stream zu kopieren?
Muss der String, damit er entschlüsselt werden kann, eigentlich genau 4 Bytes lang sein oder muss er mindestens 4 Byte lang sein? Hintergrund: Du schreibst das "eigentlich alles UTF8 kodiert sein" soll. Die Byte Order Mark (BOM) von UTF-8 ist 3 Bytes lang.
Grüße
Friemler
die Länge des BlowFish-Streams wird intern anscheinend durch eine Suchoperation bestimmt. Kann die Längenangabe (Parameter 2) der CopyFrom-Methode wie in Delphi auf 0 gesetzt werden, um den gesamten Stream zu kopieren?
Muss der String, damit er entschlüsselt werden kann, eigentlich genau 4 Bytes lang sein oder muss er mindestens 4 Byte lang sein? Hintergrund: Du schreibst das "eigentlich alles UTF8 kodiert sein" soll. Die Byte Order Mark (BOM) von UTF-8 ist 3 Bytes lang.
Grüße
Friemler
Hallo Ankh
Solange keine UTF-8 Byte Order Mark und auch keine Zeichen mit einem Code größer 127 in der Datei enthalten sind, lassen sich ANSI und UTF-8 Dateien nicht unterscheiden.
Ich schätze, da musst Du mal in die RTL von FPC rein debuggen und herausfinden, durch welche Umstände der Fehler entsteht. Evtl. hast Du da einen noch nicht entdeckten Bug gefunden.
Gerne wieder!
Bei mir zahlt der Cheffe.
Grüße
Friemler
Notepad++ sagt übrigens, dass die Datei Ansi-kodiert ist ... ?
Solange keine UTF-8 Byte Order Mark und auch keine Zeichen mit einem Code größer 127 in der Datei enthalten sind, lassen sich ANSI und UTF-8 Dateien nicht unterscheiden.
Ich schätze, da musst Du mal in die RTL von FPC rein debuggen und herausfinden, durch welche Umstände der Fehler entsteht. Evtl. hast Du da einen noch nicht entdeckten Bug gefunden.
Danke für deine Unterstützung!
Gerne wieder!
Ich wäre ja gern bei Delphi geblieben, aber die Preispolitik hat mich rausgeschmissen.
Bei mir zahlt der Cheffe.
Grüße
Friemler
Hey Ankh,
Von der neuesten Delphi-Version 10.3 Rio gibt es eine Community Edition für umme. Damit kann man sogar kommerzielle Software entwickeln, wenn die Firma höchstens 5 Entwickler beschäftigt und höchstens $5000 Umsatz pro Jahr macht (wie davon 5 Entwickler oder auch nur einer leben sollen verraten sie nicht).
Mehr Infos und Links zum Download hier: https://www.embarcadero.com/products/delphi/starter
Grüße
Friemler
Frag doch bitte Cheffe, ob er mich vielleicht sponsoren möchte.
Von der neuesten Delphi-Version 10.3 Rio gibt es eine Community Edition für umme. Damit kann man sogar kommerzielle Software entwickeln, wenn die Firma höchstens 5 Entwickler beschäftigt und höchstens $5000 Umsatz pro Jahr macht (wie davon 5 Entwickler oder auch nur einer leben sollen verraten sie nicht).
Mehr Infos und Links zum Download hier: https://www.embarcadero.com/products/delphi/starter
Grüße
Friemler