Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Frage Betreffs einer simplen Verschlüsselung (https://www.delphipraxis.net/126131-frage-betreffs-einer-simplen-verschluesselung.html)

Sonic-Y3k 18. Dez 2008 15:24


Frage Betreffs einer simplen Verschlüsselung
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hi,
ich habe folgendes Denkproblem, ich würde gerne mit einem Filestream jeweils in kleinen Blöcken Datein, egal welcher Art laden und die Zeichen mittels Verschiebung ändern.
Leider kommt bei mir immer nur Quatsch bei raus, vlt. könnt ihr mir helfen.

Gruß,

Delphi-Quellcode:
unit UnitMainForm;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ComCtrls;

type
  TMainForm = class(TForm)
    ButtonEncrypt: TButton;
    OpenDialogEncrypt: TOpenDialog;
    Memo1: TMemo;
    Button1: TButton;
    ProgressBar1: TProgressBar;
    function Encode(what: string; key: Integer): WideString;
    function Decode(what: string; key: Integer): WideString;
    function GenerateKey: Integer;
    procedure ButtonEncryptClick(Sender: TObject);
    procedure HandleFile(done:Longint; Filename: String);
    procedure Button1Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  MainForm: TMainForm;

implementation

{$R *.dfm}

function TMainForm.Encode(what: string; key: Integer): WideString;
var
  i, o: integer;
  res: string;
begin
  i:= 0;
  while i < length(what)-1 do
  begin
    o:= ord(what[i])+key;
    if o > 255 then
      o := o-255;

    res := res+chr(o);
    if what[i+1] = '' then
      i:= length(what)
    else
      inc(i);
  end;
  Result:= res;
end;

function TMainForm.Decode(what: string; key: Integer): WideString;
var
  i, o: integer;
  res: string;
begin
  for i:=0 to length(what)-1 do
  begin
    o:= ord(what[i])-key;
    if o < 0 then
      o := o+255;

    res := res+chr(o);
  end;
  Result:= res;
end;

function TMainForm.GenerateKey: Integer;
begin
  randomize;

  Result:= random(79)+20;
end;

procedure TMainForm.Button1Click(Sender: TObject);
const
  BufferSize= 1024;
var
  WStream,Stream: TFileStream;
  d,Buffer: WideString;
  done: LongInt;
  Key: Integer;
begin
  if OpenDialogEncrypt.Execute then
  try
    Stream := TFileStream.Create(OpenDialogEncrypt.FileName, fmOpenRead);
    WStream := TFileStream.Create(OpenDialogEncrypt.FileName+'.txt', fmOpenWrite or fmCreate);

    Done:= 2;
    Stream.Read(Key, SizeOf(2));
    while (done < Stream.Size) do
    begin
      Stream.Seek(done, soBeginning);
      Stream.Read(Buffer[1], BufferSize);
      done := done+BufferSize;
      d:= Decode(Buffer, Key);
      WStream.Write(d[1], length(d));
    end;
  finally
      Stream.Free;
      WStream.Free;
  end;
end;

procedure TMainForm.ButtonEncryptClick(Sender: TObject);
begin
  if MainForm.OpenDialogEncrypt.Execute then
  begin
    HandleFile(0, OpenDialogEncrypt.Filename);
  end;
end;

procedure TMainForm.HandleFile(done:Longint; Filename: String);
const
  BufferSize = 1024;
var
  Stream, WStream: TFileStream;
  Buffer,d,Key: String;
  s, k: WideString;
  i: integer;
begin

  try
    SetLength(Buffer, BufferSize);
    Stream := TFileStream.Create(Filename, fmOpenRead);
    WStream := TFileStream.Create(Filename+'.txt', fmOpenWrite or fmCreate);

    Key := IntToStr(GenerateKey);
    WStream.Write(Key[1], 1);
    WStream.Write(Key[2], 1);
    WStream.Seek(2, soBeginning);
    done := 0;

    ProgressBar1.Max :=Stream.Size;
    ProgressBar1.Position := 0;
    ProgressBar1.Min := 0;

    while (done < Stream.Size) do
    begin
      Stream.Seek(done, soBeginning);
      Stream.Read(Buffer[1], BufferSize);
      done := done+BufferSize;
      ProgressBar1.Position := done;
      d:= Encode(Buffer, StrToInt(Key));
      WStream.Write(d[1], length(d));
    end;

  finally
      Stream.Free;
      WStream.Free;
  end;
end;

end.

Blup 19. Dez 2008 13:28

Re: Frage Betreffs einer simplen Verschlüsselung
 
Korrekturen und Komentare im Quelltext
Delphi-Quellcode:
function Encode(what: string; key: Integer): WideString;
var
  i, o: integer;
  res: string;
begin
  i:= 1;                     // String beginnt mit Index 1     
  while i <= length(what) do // Das letzte Zeichen auch verschlüsseln
  begin
    o:= ord(what[i])+key;
    if o > 255 then
      o := o-256;            // 256..511 -> 0..255 

    res := res+chr(o);
                              //    if what[i+1] = '' then // Die Bedingung ist in der Schleife nie erfüllt.
                              //      i:= length(what)
                              //    else
      inc(i);
  end;
  Result:= res;
end;

function Decode(what: string; key: Integer): WideString;
var
  i, o: integer;
  res: string;
begin
  for i:=1 to length(what) do // String beginnt mit Index 1 
  begin
    o:= ord(what[i])-key;
    if o < 0 then
      o := o+256;            // -256..-1 -> 0..255

    res := res+chr(o);
  end;
  Result:= res;
end;

function TMainForm.GenerateKey: Integer;
begin
  randomize;

  Result:= random(79)+20;   // 20..98
end;

procedure TMainForm.Button1Click(Sender: TObject);
const
  BufferSize= 1024;
var
  WStream,Stream: TFileStream;
  Buffer: String;                   // String reicht
  done, datasize: LongInt;
  Key: Integer;
begin
  if OpenDialogEncrypt.Execute then
  begin
    Stream := nil;                      // Falls eine Exception beim Erzeugen der Streams auftritt
    WStream := nil;                      // ist Free auf nil-Pointer zulässig
    try
      Stream := TFileStream.Create(OpenDialogEncrypt.FileName, fmOpenRead);
      WStream := TFileStream.Create(OpenDialogEncrypt.FileName+'.txt', fmOpenWrite or fmCreate);

      done := Stream.Size;
      datasize := 2;                     // Wie viele Daten sollen tatsächlich gelesen werden
      SetLength(Buffer, datasize);       // Speicher für den Buffer reservieren
      Stream.Read(Buffer[1], datasize);  // Stream.Read(Key, SizeOf(2));
      Dec(done, datasize);               // Anzahl der restlichen Byte im Stream
      Key := StrToInt(Buffer);           // Zeichenkette umwandeln

      while (done > 0) do
      begin
        datasize = Min(done, BufferSize); // Maximal Daten von der Größe des Buffers lesen
                                          // Stream.Seek(done, soBeginning); Position wird durch Lesen erreicht
        SetLength(Buffer, datasize);
        Stream.Read(Buffer[1], datasize);
        Dec(done, datasize);
        Buffer:= Decode(Buffer, Key);
        WStream.Write(Buffer[1], datasize);
      end;
    finally
      Stream.Free;
      WStream.Free;
    end;
  end;
end;

procedure TMainForm.ButtonEncryptClick(Sender: TObject);
begin
  if MainForm.OpenDialogEncrypt.Execute then
  begin
    HandleFile(0, OpenDialogEncrypt.Filename);
  end;
end;

procedure TMainForm.HandleFile(done:Longint; Filename: String);
const
  BufferSize = 1024;
var
  Stream, WStream: TFileStream;
  Buffer: String;
  done, datasize: LongInt;
  Key, i: integer;
begin
  Stream := nil;                      // Falls eine Exception auftritt
  WStream := nil;                      // ist Free auf nil-Pointer zulässig
  try
                                        // SetLength(Buffer, BufferSize);
    Key := GenerateKey;
    Buffer := IntToStr(Key);
 
    case Key of                        // Key könnte eigentlich im Bereich 0..255 liegen
      0..9:  Buffer := '0' + Buffer;          
      10..99: ;                        // durch die Art der Speicherung auf 2stellig beschränkt
    else
      raise Excpetion.Create(Format('Key %d liegt nicht im gültigen Bereich', [Key]);
    end;

    Stream := TFileStream.Create(Filename, fmOpenRead);
    WStream := TFileStream.Create(Filename+'.txt', fmOpenWrite or fmCreate);

    WStream.Write(Buffer[1], Length(Buffer)); // kompletten Key als Zeichenfolge speichern
                                               // WStream.Seek(2, soBeginning);
    done := Stream.Size;

    ProgressBar1.Max     := done;
    ProgressBar1.Position := 0;
    ProgressBar1.Min     := 0;

    while (done > 0) do
    begin
                                               // Stream.Seek(done, soBeginning);
      datasize = Min(done, BufferSize);
      SetLength(Buffer, datasize);
      Stream.Read(Buffer[1], datasize);
      Dec(done, datasize);
      Buffer:= Encode(Buffer, Key);
      WStream.Write(Buffer[1], datasize);

      ProgressBar1.Position := ProgressBar1.Max - done;
    end;
  finally
    Stream.Free;
    WStream.Free;
  end;
end;

end.
Und noch ein Vorschlag zur Vereinfachung
Delphi-Quellcode:
function Encode(what: string; key: Integer): String;
var
  i: integer;
begin
  Result := what;
  for i := 1 to length(Result) do
    Result[i] := Char((Ord(Result[i]) + Key) mod 256);
end;

function Decode(what: string; key: Integer): String;
var
  i: integer;
begin
  Result := what;
  for i := 1 to length(Result) do
    Result[i] := Char((Ord(Result[i]) - Key) mod 256);
end;
Alles ungetestet und ohne Gewährleistung

himitsu 19. Dez 2008 13:46

Re: Frage Betreffs einer simplen Verschlüsselung
 
Delphi-Quellcode:
//    if what[i+1] = '' then // Die Bedingung ist in der Schleife nie erfüllt.
//      i:= length(what)
//    else
das wird nie erfüllt (auch außerhalb von Schleifen)

ein Zeichen (Char) kann nie mal kein Zeichen (Leerstring) sein ...

und i+1 würde (jetzt wo du das Stingende korrigiert hast)
Delphi-Quellcode:
// String beginnt mit Index 1     
// Das letzte Zeichen auch verschlüsseln
bis außerhalb des Strings reichen, also hinter den String zeigen ...
sozusagen auf what[(Length(wath) + 1]

Blup 19. Dez 2008 14:23

Re: Frage Betreffs einer simplen Verschlüsselung
 
Zitat:

Zitat von himitsu
das wird nie erfüllt (auch außerhalb von Schleifen)

Bei genauerer Betrachtung kann die Bedingung doch erfüllt sein.
Der Vergleich wird so übersetzt: what[i+1] = Char(0).

Der Vergleich ist an dieser Stelle nur sachlich falsch, da Nullzeichen auch im String vorkommen können.

himitsu 19. Dez 2008 14:34

Re: Frage Betreffs einer simplen Verschlüsselung
 
Zitat:

Zitat von Blup
Der Vergleich wird so übersetzt: what[i+1] = Char(0).

hmmmmm :gruebel:
eigentlich hätt ich gedacht es würde eher so übersetzt: String(what[i+1]) = ''

Delphi-Quellcode:
var c: Char;

c := #0;
if c = '' then
  Application.MessageBox('ok, es geht doch', '@_@');
ausprobiert und stimmt :shock:

Sonic-Y3k 20. Dez 2008 08:42

Re: Frage Betreffs einer simplen Verschlüsselung
 
Hi,
Zunächst erstmal Danke, wusste echt nicht mehr weiter!
An sich gibt es jetzt nur noch ein Problem, das Problem ist dass das Programm nur den halben Key in das File schreibt und es deswegen natürlich nicht funktioniert...

Als Beispiel: Der Key ist 60, dann würde am Anfang der Datei nur 6 Stehen, was ein Decodieren natürlich unmöglich macht.

Delphi-Quellcode:
procedure TMainForm.HandleFile(done:Longint; Filename: String);
const
  BufferSize = 1024;
var
  Stream, WStream: TFileStream;
  Buffer: String;
  adone, datasize: LongInt;
  Key, i: integer;
begin
  Stream := nil;                      // Falls eine Exception auftritt
  WStream := nil;                      // ist Free auf nil-Pointer zulässig
  try
                                        // SetLength(Buffer, BufferSize);
    Key := GenerateKey;
    Buffer := IntToStr(Key);
    ShowMessage(IntToStr(Key));
    case Key of                        // Key könnte eigentlich im Bereich 0..255 liegen
      0..9:  Buffer := '0' + Buffer;
      10..99: ;                        // durch die Art der Speicherung auf 2stellig beschränkt
    else
      ShowMessage(Format('Key %d liegt nicht im gültigen Bereich', [Key]));
      exit;
    end;

    Stream := TFileStream.Create(Filename, fmOpenRead);
    WStream := TFileStream.Create(Filename+'.backup', fmOpenWrite or fmCreate);

    WStream.Write(Buffer[1], Length(Buffer)); // kompletten Key als Zeichenfolge speichern
    adone := Stream.Size;

    ProgressBar1.Max     := adone;
    ProgressBar1.Position := 0;
    ProgressBar1.Min     := 0;

    while (adone > 0) do
    begin
                                               // Stream.Seek(done, soBeginning);
      datasize := Min(adone, BufferSize);
      SetLength(Buffer, datasize);
      Stream.Read(Buffer[1], datasize);
      Dec(adone, datasize);
      Buffer:= Encode(Buffer, Key);
      WStream.Write(Buffer[1], datasize);

      ProgressBar1.Position := ProgressBar1.Max - adone;
    end;
  finally
    Stream.Free;
    WStream.Free;
  end;
end;
Gruß,

Sonic-Y3k 22. Dez 2008 13:27

Re: Frage Betreffs einer simplen Verschlüsselung
 
Liste der Anhänge anzeigen (Anzahl: 1)
So, bin wieder einen Schritt weitergekommen, aber es gibt nach wie vor Probleme, so ist es mir zum Beispiel mittlerweile zwar möglich einen Stream zu speichern, auch so dass am Anfang der Datei der Key steht, und das ganze auch zu wieder zu Laden und den Key zu extrahieren.

Allerdings gibt es dafür neue Probleme:

Wenn zum Beispiel in einer Datei

Zitat:

Hallo
steht, kommt dabei

Zitat:

72° ´ ·
heraus, und wenn man das ganze decodiert:

Zitat:

h l o
man sieht also dass nur jedes zweites Zeichen gelesen wird.

Hier nochmal die ganze Unit in der es zum En- und Decodieren nur noch eine Procedure gibt:

Delphi-Quellcode:
unit UnitMainForm;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ComCtrls,Math;

type
  TMainForm = class(TForm)
    ButtonEncrypt: TButton;
    OpenDialogEncrypt: TOpenDialog;
    Memo1: TMemo;
    ButtonDecrypt: TButton;
    ProgressBar1: TProgressBar;
    function GenerateKey: Integer;
    procedure ButtonEncryptClick(Sender: TObject);
    procedure HandleFile(done:Longint; Filename: String; Mode: Boolean);
    procedure ButtonDecryptClick(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  MainForm: TMainForm;

implementation

{$R *.dfm}

function Encode(what: string; key: Integer): String;
var
  i: integer;
begin
  Result := what;
  for i := 1 to length(Result) do
    Result[i] := Char((Ord(Result[i]) + Key) mod 256);
end;

function Decode(what: string; key: Integer): String;
var
  i: integer;
begin
  Result := what;
  for i := 1 to length(Result) do
    Result[i] := Char((Ord(Result[i]) - Key) mod 256);
end;

function TMainForm.GenerateKey: Integer;
begin
  randomize;

  Result:= random(79)+20;
end;

procedure TMainForm.ButtonDecryptClick(Sender: TObject);
begin
  if MainForm.OpenDialogEncrypt.Execute then
  begin
    HandleFile(0, OpenDialogEncrypt.FileName, true);
  end;
end;

procedure TMainForm.ButtonEncryptClick(Sender: TObject);
begin
  if MainForm.OpenDialogEncrypt.Execute then
  begin
    HandleFile(0, OpenDialogEncrypt.Filename, false);
  end;
end;

procedure TMainForm.HandleFile(done:Longint; Filename: String; Mode: Boolean);
const
  BufferSize = 1024;
var
  Stream, WStream: TFileStream;
  Buffer: String;
  adone, datasize: LongInt;
  Key, i: integer;
begin
  Stream := nil;                      // Falls eine Exception auftritt
  WStream := nil;                      // ist Free auf nil-Pointer zulässig
  try
                                        // SetLength(Buffer, BufferSize);
    Key := GenerateKey;

    Stream := TFileStream.Create(Filename, fmOpenRead);

    if Mode = true then
    begin
      SetLength(Buffer,2);
      WStream := TFileStream.Create(Copy(Filename,1, Pos('.backup', Filename)), fmOpenWrite or fmCreate);
      Stream.Position := 0;

      Stream.ReadBuffer(Buffer[1], 1);
      Stream.ReadBuffer(Buffer[2], 1);

      Key := StrToInt(Buffer[1]+Buffer[2]);
      adone := Stream.Size-2;
      Buffer := '';
    end else if Mode = false then
    begin
      Buffer := IntToStr(Key);
      WStream := TFileStream.Create(Filename+'.backup', fmOpenWrite or fmCreate);
      WStream.Write(Buffer[1], 1); // kompletten Key als Zeichenfolge speichern
      WStream.Write(Buffer[2], 1);
      adone := Stream.Size;
    end;

    case Key of                        // Key könnte eigentlich im Bereich 0..255 liegen
      20..99: ;                        // durch die Art der Speicherung auf 2stellig beschränkt
    else
      ShowMessage(Format('Key %d liegt nicht im gültigen Bereich', [Key]));
      exit;
    end;

    ShowMessage(IntToStr(Key));

    ProgressBar1.Max     := adone;
    ProgressBar1.Position := 0;
    ProgressBar1.Min     := 0;

    while (adone > 0) do
    begin
                                               // Stream.Seek(done, soBeginning);
      datasize := Min(adone, BufferSize);
      SetLength(Buffer, datasize);
      Stream.Read(Buffer[1], datasize);
      Dec(adone, datasize);
      ShowMessage(Buffer);
      if Mode = true then
        Buffer:= Decode(Buffer, Key)
      else if Mode = false then
        Buffer:= Encode(Buffer, Key);

      WStream.Write(Buffer[1], datasize);

      ProgressBar1.Position := ProgressBar1.Max - adone;
    end;
  finally
    Stream.Free;
    WStream.Free;
  end;
end;

end.
Habt ihr vlt. irgendwelche Ideen?

Gruß Sonic


Alle Zeitangaben in WEZ +1. Es ist jetzt 16:35 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz