Xorowanie strumieni

Misiekd

Klasa nie jest mojego pomysłu, jej implementację znalazłem gdzieś na sieci.

Jest to klasa, która w prosty sposób koduje strumień przy pomocy XORowania.

unit XorStreamCipher;

interface

uses
  SysUtils, Classes;

type
  TXorStreamCipher = class
  private
    FPassStream: TStream;
    FInStream: TStream;
    FOutStream: TStream;
    procedure SetInStream(const Value: TStream);
    procedure SetOutStream(const Value: TStream);
    procedure SetPassStream(const Value: TStream);
  public
    procedure Process;
    property InStream: TStream Read FInStream Write SetInStream;
    property OutStream: TStream Read FOutStream Write SetOutStream;
    property PassStream: TStream Read FPassStream Write SetPassStream;
  end;

implementation

{ TXorStreamCipher }

procedure TXorStreamCipher.Process;

  function StreamsAssigned: boolean;
  begin
    Result := Assigned(FInStream) and Assigned(FOutStream) and Assigned(FPassStream);
  end;

  function StreamsDifferent: boolean;
  begin
    Result := (FInStream <> FOutStream) and (FOutStream <> FPassStream) and (FPassStream <> FInStream);
  end;

  procedure RewindStream(const AStream: TStream);
  begin
    AStream.Seek(0, soFromBeginning);
  end;

  function GetByte(const AStream: TStream): byte;
  begin
    AStream.Read(Result, SizeOf(byte))
  end;

  procedure PutByte(const AStream: TStream; const AByte: byte);
  begin
    AStream.Write(AByte, SizeOf(byte));
  end;

  function Eos(const AStream: TStream): boolean;
  begin
    with AStream do
      Result := (Position = {Pred}(Size));
  end;

begin
  if StreamsAssigned and StreamsDifferent then
  begin
    RewindStream(FInStream);
    RewindStream(FOutStream);
    RewindStream(FPassStream);
    while not Eos(FInStream) do
    begin
      PutByte(FOutStream, GetByte(FInStream) xor GetByte(FPassStream));
      if Eos(FPassStream) then
        RewindStream(FPassStream);
    end;
  end
  else
    raise Exception.Create('You must assign all 3 streams to properties.');
end;

procedure TXorStreamCipher.SetInStream(const Value: TStream);
begin
  FInStream := Value;
end;

procedure TXorStreamCipher.SetOutStream(const Value: TStream);
begin
  FOutStream := Value;
end;

procedure TXorStreamCipher.SetPassStream(const Value: TStream);
begin
  FPassStream := Value;
end;

end.

przykład użycia

var
  InStream, OutStream: TFileStream;
  PassStream: TMemoryStream;
  XorStream: TXorStreamCipher;
  pass: string;
begin
  InStream := TFileStream.Create('ścieżka i nazwa pliku in', fmOpenRead or fmShareExclusive);
  OutStream := TFileStream.Create('ścieżka i nazwa pliku out', fmCreate);
  PassStream := TMemmoryStream.Create;
  XorStream := TXorStreamCipher.Create;
  try
    PassStream.Write(pass, Length(pass)); //można też np. wczytać z pliku
    XorStream.PassStream := PassStream;
    XorStream.InStream := InStream;
    XorStream.OutStream := OutStream;
    XorStream.Process;
  finally
    FreeAndNil(InStream);
    FreeAndNil(OutStream);
    FreeAndNil(PassStream);
    FreeAndNil(XorStream);
  end;
end;

Deszyfrowanie to po prostu zaszyfrowanie pliku raz jeszcze

2 komentarzy

Fajnie, tyle że zamienia wszystkie znaki na spacjo-podobne :> a tu chyba o to nie chodzi