Entwickler-Ecke

Dateizugriff - Verschlüsseltes Laden und Speichern einer TStringList


ub60 - Sa 18.08.18 22:10
Titel: Verschlüsseltes Laden und Speichern einer TStringList
Hallo miteinander,

ich möchte Inhalte einer Stringliste (oder Listbox) verschlüsselt abspeichern und natürlich auch wieder einlesen können. Die Qualität der Verschlüsselung muss nicht NSA-sicher :wink: sein, es soll nur nicht gleich jeder den Inhalt erkennen, dem die Datei zufällig in die Hand fällt.
Beim Recherchieren habe ich folgendes [https://www.delphipraxis.net/135493-stringlist-verschluesseln-welche-methode-ist-am-besten.html]gefunden.
Leider läuft diese Variante wohl erst in "neueren" Delphi-Versionen, ich würde es aber für ein älteres Programm in Delphi7 benötigen. Bisher erhalte ich beim Compilieren des verlinkten Quelltextes die Fehlermeldung "System-Unit veraltet oder beschädigt: 'TClassHelperBase' fehlt".

Hat eventuell jemand eine Idee, die auch mit D7 funktioniert?

Danke schon mal!
ub60


Mathematiker - Sa 18.08.18 22:34

Hallo ub60,
genügt ein Speichern mit zlib ?
Die Daten sind zwar nicht verschlüsselt, aber ein Laie kann den Inhalt der Datei nicht lesen.

Ich nutze zum Speichern und Laden einer Stringliste:

Delphi-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:
uses zlib;

procedure CompressStream(inpStream, outStream: TStream);
var
  InpBuf, OutBuf: Pointer;
  InpBytes, OutBytes: Integer;
begin
  InpBuf := nil;
  OutBuf := nil;
  try
    GetMem(InpBuf, inpStream.Size);
    inpStream.Position := 0;
    InpBytes := inpStream.Read(InpBuf^, inpStream.Size);
    CompressBuf(InpBuf, InpBytes, OutBuf, OutBytes);
    outStream.Write(OutBuf^, OutBytes);
  finally
    if InpBuf <> nil then FreeMem(InpBuf);
    if OutBuf <> nil then FreeMem(OutBuf);
  end;
end;

procedure DecompressStream(inpStream, outStream: TStream);
var
  InpBuf, OutBuf: Pointer;
  OutBytes, sz: Integer;
begin
  InpBuf := nil;
  OutBuf := nil;
  sz     := inpStream.Size - inpStream.Position;
  if sz > 0 then
    try
      GetMem(InpBuf, sz);
      inpStream.Read(InpBuf^, sz);
      DecompressBuf(InpBuf, sz, 0, OutBuf, OutBytes);
      outStream.Write(OutBuf^, OutBytes);
    finally
      if InpBuf <> nil then FreeMem(InpBuf);
      if OutBuf <> nil then FreeMem(OutBuf);
    end;
  outStream.Position := 0;
end;

procedure savememoryliste(liste:tstringlist;const dateiname:string);
var ms1, ms2: TMemoryStream;
begin
  ms1 := TMemoryStream.Create;
  try
    ms2 := TMemoryStream.Create;
    try
      liste.SaveToStream(ms1);
      CompressStream(ms1, ms2);
      ms2.SaveToFile(dateiname);
    finally
      ms2.Free;
    end;
  finally
    ms1.Free;
  end;
end;

procedure loadmemoryliste(liste:tstringlist;const dateiname:string);
var
  ms1, ms2: TMemoryStream;
begin
  ms1 := TMemoryStream.Create;
  try
    ms2 := TMemoryStream.Create;
    try
      ms1.LoadFromFile(dateiname);
      DecompressStream(ms1, ms2);
      liste.LoadFromStream(ms2);
    finally
      ms2.Free;
    end;
  finally
    ms1.Free;
  end;
end;


LG Steffen


Narses - Sa 18.08.18 23:08

Moin!

user profile iconub60 hat folgendes geschrieben Zum zitierten Posting springen:
Hat eventuell jemand eine Idee, die auch mit D7 funktioniert?
Ich hab hier mal einen RC4-Stream-Adapter unter D7 [https://www.entwickler-ecke.de/viewtopic.php?p=563921#563921] gebaut, vielleicht hilft´s. :nixweiss:

cu
Narses


ub60 - So 19.08.18 11:26

@Mathematiker:

Vielen Dank! Das sieht prinzipiell ganz gut aus, aber etwas :) verschlüsselt sollte es schon sein.

@Narses:

Mit Dateien funktioniert das in D7 ganz gut, aber ich möchte es aus einem Memorystream speichern. Leider bekomme ich da eine Fehlermeldung.

Eventuell sieht ja jemand meinen Fehler:


Delphi-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:
uses rc4;

procedure TForm1.WriteBtnClick(Sender: TObject);
var ListboxStream: TMemoryStream;
    RC4Writer: TRC4StreamWriter;
begin
  ListboxStream:=TMemoryStream.Create;
  try
    ListBox1.Items.SaveToStream(ListboxStream);
    ShowMessage(IntToStr(ListboxStream.Size));  // funktioniert
    // es wird auch noch eine leere Datei erzeugt
    RC4Writer := TRC4StreamWriter.Create(TFileStream.Create('ausgabe.txt', fmCreate or fmShareDenyWrite), 'geheim');
    try
      // Hier kommt der Fehler
      // ... ist eine Exception der Klasse EReadError aufgetreten.
      // Meldung: 'Stream-Lesefehler'.
      RC4Writer.CopyFrom(ListboxStream, ListboxStream.Size);      
    finally
      RC4Writer.Free;
    end;
  finally
    ListboxStream.Free;
  end;
end;

ub60


Narses - So 19.08.18 14:09

Moin!

user profile iconub60 hat folgendes geschrieben Zum zitierten Posting springen:
Mit Dateien funktioniert das in D7 ganz gut, aber ich möchte es aus einem Memorystream speichern. Leider bekomme ich da eine Fehlermeldung.

Eventuell sieht ja jemand meinen Fehler:
Ich würde mal raten (ohne das jetzt selbst auszuprobieren), du muss den Stream wieder "zurückspulen", also sowas:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
  ListboxStream:=TMemoryStream.Create;
  try
    ListBox1.Items.SaveToStream(ListboxStream);
    ListboxStream.Position := 0// Stream wieder auf Anfang
    ShowMessage(IntToStr(ListboxStream.Size));  // funktioniert
    ...

Die Klasse funktioniert, benutze ich in mehreren Projekten selbst. :nixweiss:

cu
Narses


ub60 - So 19.08.18 16:09

user profile iconNarses hat folgendes geschrieben Zum zitierten Posting springen:


Delphi-Quelltext
1:
2:
3:
    ListBox1.Items.SaveToStream(ListboxStream);
    ListboxStream.Position := 0// Stream wieder auf Anfang
    ShowMessage(IntToStr(ListboxStream.Size));


Vielen Dank, das war es!

Ich lass das Theme mal offen, falls hier noch andere Lösungen/Verfahren kommen.

ub60