AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Code-Bibliothek Library: Algorithmen Delphi RC4-Verschlüsselung

RC4-Verschlüsselung

Ein Thema von CalganX · begonnen am 28. Jul 2004 · letzter Beitrag vom 18. Apr 2005
Antwort Antwort
CalganX

Registriert seit: 21. Jul 2002
Ort: Bonn
5.403 Beiträge
 
Turbo Delphi für Win32
 
#1

RC4-Verschlüsselung

  Alt 28. Jul 2004, 11:29
Hagen hat hier eine Routine für eine RC4-Verschlüsselung gepostet:
Delphi-Quellcode:
type
  TRC4Context = record
    D: array[Byte] of Byte;
    I,J: Byte;
  end;

procedure RC4Init(var RC4: TRC4Context; const Key: String);
var
  R,S,T,K: Byte;
  U,L: Integer;
begin
  L := Length(Key);
  with RC4 do
  begin
    I := 0;
    J := 0;
    for S := 0 to 255 do D[S] := S;
    R := 0;
    U := 0;
    for S := 0 to 255 do
    begin
      if U < L then K := PByteArray(Key)[U] else K := 0;
      Inc(U);
      if U >= L then U := 0;

      Inc(R, D[S] + K);
      T := D[S];
      D[S] := D[R];
      D[R] := T;
    end;
  end;
end;

procedure RC4Code(var RC4: TRC4Context; const Source; var Dest; Count: Integer);
var
  S: Integer;
  T: Byte;
begin
  with RC4 do
    for S := 0 to Count -1 do
    begin
      Inc(I);
      T := D[I];
      Inc(J, T);
      D[I] := D[J];
      D[J] := T;
      Inc(T, D[I]);
      TByteArray(Dest)[S] := TByteArray(Source)[S] xor D[T];
    end;
end;

procedure RC4Done(var RC4: TRC4Context);
begin
  FillChar(RC4, SizeOf(RC4), 0);
end;
maximov hat dafür eine kurzes Verwendungsbeispiel gepostet:
Delphi-Quellcode:
var
  x: TRC4Context;
  str1, str2, str3: string;
begin
  readLn(str1);
  setLength(str2,length(str1));
  writeLn('text: '+str1);
 
  RC4Init(x,'Passwort');
  RC4Code(x, str1[1], str2[1], Length(str1)); // verschlüsseln
  Rc4Done(x);
 
  writeLn('coded: '+str2);
  setLength(str3,length(str2));

  RC4Init(x,'Passwort');
  RC4Code(x, str2[1], str3[1], Length(str2)); // entschlüsseln
  Rc4Done(x);
   
  writeLn('encoded: '+str3);
  readLn;
end.
»Mein Kaffee ist so schwarz — der fängt gleich an zu rappen...«
  Mit Zitat antworten Zitat
Benutzerbild von maximov
maximov

Registriert seit: 2. Okt 2003
Ort: Hamburg
548 Beiträge
 
Delphi 2005 Professional
 
#2

Re: RC4-Verschlüsselung

  Alt 30. Jul 2004, 18:40
N'abend 8)

Hier die RC4 unit (ich hoffe Hagen ist damit einverstanden):

Delphi-Quellcode:
unit HagEnCode;

// Code written by Hagen ([url]http://www.delphipraxis.net/topic12881,15.html[/url])

// unit created by maximov 29.07.2004

interface

type
  TRC4Context = record
    D: array[Byte] of Byte;
    I,J: Byte;
  end;
  
procedure RC4Init(var RC4: TRC4Context; const Key: String);
procedure RC4Code(var RC4: TRC4Context; const Source; var Dest; Count: Integer); overload;
function RC4Code(var RC4: TRC4Context; const Value: String): String; overload;
function RC4Code(const Value, Password: String): String; overload;
procedure RC4Done(var RC4: TRC4Context);


procedure RC4Seed(const Seed: String);
function TRC4Random: Cardinal;

implementation

type
  PByteArray = ^TByteArray;
  TByteArray = array[0..($FFFF shr 1)-1] of byte;

var
  RC4Random: TRC4Context;


function RC4Code(var RC4: TRC4Context; const Value: String): String; overload;
var
  Count: Integer;
begin
  Count := Length(Value);
  SetLength(Result, Count);
  RC4Code(RC4, Value[1], Result[1], Count);
end;

function RC4Code(const Value, Password: String): String; overload;
var
  RC4: TRC4Context;
begin
  RC4Init(RC4, Password);
  try
    Result := RC4Code(RC4, Value);
  finally
    RC4Done(RC4);
  end;
end;


procedure RC4Init(var RC4: TRC4Context; const Key: String);
var
  R,S,T,K: Byte;
  U,L: Integer;
begin
  L := Length(Key);
  with RC4 do
  begin
    I := 0;
    J := 0;
    for S := 0 to 255 do D[S] := S;
    R := 0;
    U := 0;
    for S := 0 to 255 do
    begin
      if U < L then K := PByteArray(Key)[U] else K := 0;
      Inc(U);
      if U >= L then U := 0;

      Inc(R, D[S] + K);
      T := D[S];
      D[S] := D[R];
      D[R] := T;
    end;
  end;
end;

procedure RC4Code(var RC4: TRC4Context; const Source; var Dest; Count: Integer);
var
  S: Integer;
  T: Byte;
begin
  with RC4 do
    for S := 0 to Count -1 do
    begin
      Inc(I);
      T := D[I];
      Inc(J, T);
      D[I] := D[J];
      D[J] := T;
      Inc(T, D[I]);
      TByteArray(Dest)[S] := TByteArray(Source)[S] xor D[T];
    end;
end;

procedure RC4Done(var RC4: TRC4Context);
begin
  FillChar(RC4, SizeOf(RC4), 0);
end;





procedure RC4Seed(const Seed: String);
begin
  RC4Init(RC4Random, Seed);
end;

function TRC4Random: Cardinal;
type
  PRC4Cast = ^TRC4Cast;
  TRC4Cast = record
    FirstSBOX: Cardinal;
  end;

begin
// verschlüssele die dynamsiche SBOX von RC4Random.D mit sich selber und gebe die 4 ersten Bytes
// als Zufallswert zurück !!
  RC4Code(RC4Random, RC4Random.D, RC4Random.D, SizeOf(RC4Random.D));
  Result := PRC4Cast(@RC4Random).FirstSBOX;
end;

initialization
  RC4Seed('5C103319-9C6F-4F88-BBDC-752779958047');
  
finalization

end.
[edit=Chakotay1308]Stream-Klasse auf Wunsch von maximov entfernt. Stattdessen sollte der RCx-Stromdekorier verwendet werden. Mfg, Chakotay1308[/edit]
[edit=SirThornberry]Link angepasst - Mfg, SirThornberry[/edit]
mâxîmôv.

{KDT}
  Mit Zitat antworten Zitat
CalganX

Registriert seit: 21. Jul 2002
Ort: Bonn
5.403 Beiträge
 
Turbo Delphi für Win32
 
#3

Re: RC4-Verschlüsselung

  Alt 18. Apr 2005, 15:27
negaH hat diesen Algorithmus erweitert von RC4 auf RCx:
(Die objektorientierte Kapselung der Funktionen inklusive Stromdekorier von maximov findet man hier)

Ok, hier meine RCx Abwandlung von RC4

Delphi-Quellcode:
{
Copyright:      2002 Hagen Reddmann
Author:        Hagen Reddmann, HaReddmann bei T-Online punkt de
Remarks:        All rights reserved
Version:        open source, developed on D5
Description:    derivate of RC5 stream cipher with internal cipher feedback and stronger keysetup
                includes secure one way pseudo random number generator
}


unit RCx;
{$A+,B-,C-,D-,E-,F-,G+,H+,I-,J+,K-,L-,M-,N+,O+,P+,Q-,R-,S-,T-,U+,V+,W-,X+,Y-,Z1}

interface

type
  TRCxContext = record
    D: array[Byte] of Byte;
    I,J,F: Byte;
  end;

procedure RCxInit(var RCx: TRCxContext; const Key; KeySize: Integer); overload;
procedure RCxInit(var RCx: TRCxContext; const Key: String); overload;
procedure RCxEncode(var RCx: TRCxContext; const Source; var Dest; Count: Integer); overload;
function RCxEncode(var RCx: TRCxContext; const Value: String): String; overload;
procedure RCxDecode(var RCx: TRCxContext; const Source; var Dest; Count: Integer); overload;
function RCxDecode(var RCx: TRCxContext; const Value: String): String; overload;
procedure RCxDone(var RCx: TRCxContext); overload;

// all in one encode/decode
function RCxEncode(const Value, Password: String): String; overload;
function RCxDecode(const Value, Password: String): String; overload;

// random number generator based on RCx
procedure RCxSeed(const Seed; SeedSize: Integer); overload;
procedure RCxSeed(const Seed: String); overload;
procedure RCxRandomize; overload;
function RCxRandom(Range: Cardinal = 0): Cardinal; overload;
function RCxRandomString(Length: Integer): String; overload;

implementation

type
  PByteArray = ^TByteArray;
  TByteArray = array[0..MaxInt -1] of Byte;

procedure RCxInit(var RCx: TRCxContext; const Key; KeySize: Integer);
var
  R,S,T,K: Byte;
  L: Integer;
  M: array[Byte] of Byte;
begin
  with RCx do
  try
    L := 0;
    for S := 0 to 255 do
    begin
      D[S] := S;
      M[S] := TByteArray(Key)[S mod KeySize] xor L;
      L := (L + M[S] * 257) mod MaxInt +1;
    end;
    I := 0;
    J := 0;
    R := L;
    F := L shr 8;
    for S := 0 to 255 do
    begin
      Inc(R, D[S] + M[S]);
      T := D[S];
      D[S] := D[R];
      D[R] := T;
    end;
  finally
    R := 0;
    S := 0;
    T := 0;
    L := 0;
    FillChar(M, SizeOf(M), 0);
  end;
end;

procedure RCxInit(var RCx: TRCxContext; const Key: String);
begin
  RCxInit(RCx, Pointer(Key)^, Length(Key));
end;

procedure RCxDone(var RCx: TRCxContext);
begin
  FillChar(RCx, SizeOf(RCx), 0);
end;

procedure RCxEncode(var RCx: TRCxContext; const Source; var Dest; Count: Integer);
var
  S: TByteArray absolute Source;
  O: TByteArray absolute Dest;
  C: Integer;
  T,K: Byte;
begin
  with RCx do
    for C := 0 to Count -1 do
    begin
      Inc(I);
      T := D[I];
      Inc(J, T);
      D[I] := D[J] xor F;
      D[J] := T - F;
      Inc(T, D[I]);

      K := S[C];
      O[C] := K xor D[T];
      F := F xor K;
    end;
end;

procedure RCxDecode(var RCx: TRCxContext; const Source; var Dest; Count: Integer);
var
  S: TByteArray absolute Source;
  O: TByteArray absolute Dest;
  C: Integer;
  T,K: Byte;
begin
  with RCx do
    for C := 0 to Count -1 do
    begin
      Inc(I);
      T := D[I];
      Inc(J, T);
      D[I] := D[J] xor F;
      D[J] := T - F;
      Inc(T, D[I]);

      K := S[C] xor D[T];
      O[C] := K;
      F := F xor K;
    end;
end;

function RCxEncode(var RCx: TRCxContext; const Value: String): String;
var
  Count: Integer;
begin
  Count := Length(Value);
  SetLength(Result, Count);
  RCxEncode(RCx, Value[1], Result[1], Count);
end;

function RCxDecode(var RCx: TRCxContext; const Value: String): String;
var
  Count: Integer;
begin
  Count := Length(Value);
  SetLength(Result, Count);
  RCxDecode(RCx, Value[1], Result[1], Count);
end;

function RCxEncode(const Value, Password: String): String;
var
  RCx: TRCxContext;
begin
  RCxInit(RCx, Password);
  try
    Result := RCxEncode(RCx, Value);
  finally
    RCxDone(RCx);
  end;
end;

function RCxDecode(const Value, Password: String): String;
var
  RCx: TRCxContext;
begin
  RCxInit(RCx, Password);
  try
    Result := RCxDecode(RCx, Value);
  finally
    RCxDone(RCx);
  end;
end;

var
  FRCxRegister: TRCxContext;

procedure RCxSeed(const Seed; SeedSize: Integer);
begin
  RCxInit(FRCxRegister, Seed, SeedSize);
end;

procedure RCxSeed(const Seed: String);
begin
  RCxSeed(Pointer(Seed)^, Length(Seed));
end;

procedure RCxRandomize;
var
  Tick: Cardinal;
begin
  Tick := GetTickCount;
  FRCxRegister.F := Tick;
  FRCxRegister.I := Tick shr 8;
  FRCxRegister.J := Tick shr 16;
  RCxEncode(FRCxRegister, FRCxRegister.D, FRCxRegister.D, SizeOf(FRCxRegister.D));
end;

function RCxRandom(Range: Cardinal): Cardinal;
type
  PCardinal = ^Cardinal;
begin
  RCxEncode(FRCxRegister, FRCxRegister.D, FRCxRegister.D, SizeOf(FRCxRegister.D));
  Result := PCardinal(@FRCxRegister.D)^;
  if Range > 1 then Result := Result mod Range;
end;

function RCxRandomString(Length: Integer): String;
var
  I: Integer;
begin
  SetLength(Result, Length);
  for I := 1 to Length do
  begin
    RCxEncode(FRCxRegister, FRCxRegister.D, FRCxRegister.D, SizeOf(FRCxRegister.D));
    Result[I] := Char(FRCxRegister.D[0]);
  end;
end;

const
  FRCxSeed: TGUID = '{F4D35205-2B59-42B0-8B8F-239855B6DD2B}';
initialization
  RCxSeed(FRCxSeed, SizeOf(FRCxSeed));
finalization
end.
Um die Unterschiede zu sehen mal eine Testfunktion

Delphi-Quellcode:
procedure TestRCx;
const
  Msg = 'Test Nachricht';
  Key = 'Test';
var
  Salt,RCx_C,RCx_D,RC4_C,RC4_D: String;
begin
  Salt := RCxRandomString(1);

  RCx_C := RCxEncode(Salt + Msg, Key);
  RCx_D := RCxDecode(RCx_C , Key);

  RC4_C := RC4Code (Salt + Msg, Key);
  RC4_D := RC4Code (RC4_D , Key);

  Delete(RCx_D, 1, Length(Salt));
  Delete(RC4_D, 1, Length(Salt));

  WriteLn('Salt: ', HexString(Salt), ' RCx_C: ', HexString(RCx_C), ' RC4_C: ', HexString(RC4_C));
end;
Dabei wird nur das erste Zeichen der zu verschlüsselten Nachricht um ein Zufallsbyte erweitert. Und nachfolgend der mehrfache Aufruf dieser Testfunktion:

Delphi-Quellcode:
Salt: D1 RCx_C: 7DCAB77ACA0C74FA2F8DDBFC3E67A6 RC4_C: AB3A283B361B402B17DFC96130F3EF
Salt: 8A RCx_C: 2634AFC68997688D5952A17D5A13FF RC4_C: F03A283B361B402B17DFC96130F3EF
Salt: FA RCx_C: 569858AC2C3BF3099957176055BD5C RC4_C: 803A283B361B402B17DFC96130F3EF
Salt: F1 RCx_C: 5D9A9E1FE91539F2AD9ADBB93D36A0 RC4_C: 8B3A283B361B402B17DFC96130F3EF
Salt: 3A RCx_C: 968344C42342DD6DEADE1735000B06 RC4_C: 403A283B361B402B17DFC96130F3EF
Salt: 7A RCx_C: D60C9A59B8959E0E8468175AB6DEE4 RC4_C: 003A283B361B402B17DFC96130F3EF
Was nun ganz deutlich auffällt ist das der CipherText des RC4 sich wirklich nur im ersten Zufallszeichen unterscheidet. Alle anderen Bytes der gleichen Nachricht werden auch immer gleich verschlüsselt bei gleichem Passwort. Mein RCx wiederrum hat dieses Merkmal nicht weil es eben die Nachrichtenbytes auch indirekt in den internen Status des RCxContext einrechnet. Dies nennt man Lawineneffekt und erhöht die Sicherheit enorm, denn nur leicht geänderte Nachricht bei gleichem Passwort erzeugt vollständig anderen Ciphertext. Alledings hat es auch einen Nachteil !! denn es wird die "Selbstsynchronisation" bei fehlerhaften Datenübertragungen zerstört. D.h. wird nur 1 Bit im Datenstrom falsch übertragen so wird der komplette Rest der verschlüsselten Nachricht eben auch falsch entschlüsselt. Das kann bei RC4 nicht passieren.

Wie man aber erkennt reicht eine Nachrichtenexpansion um Zufallsbytes bei RC4 nicht aus. Auch ein zufälliger IV ist nur eine virtuelle äußere Nachrichtenexpansion. Man muß also wirklich den RC4 Algorithmus abändern um ähnliche Effekte und Sicherheiten wie bei Blockciphern üblich zu erhalten.

Auch die Expansion des Passwortes durch einen Salt beim RC4 würde dieses Problem NICHT beseitigen !

Einen zweiten "Nachteil" erkennt man auf den ersten Blick: Statt nur einer Ver- und Entschlüsselungsfunktion wie beim RC4 benötigt man nun zwei leicht unterschiedliche Funktonen für Ver- und Entschlüsselung separat.

Am besten ist es nun vor dem Verschlüsseln der Nachrichten immer einen 16 Bytes langen Zufallsstring zu verschlüsseln und in den Ciphertext einfließen zulassen. Man expandiert also jede Nachricht amAnfang um 16 ZUfallsbytes. Bei der Entschlüsselung wird der nun zusammengesetzte CipheText in einem Rutsch entschlüsselt und die ersten 16 Bytes einfach entfernt.

Etwa so:


Delphi-Quellcode:
begin
  CipherText := RCxEncode(RCxRandomString(16) + 'Nachricht', 'Passwort');

  PlainText := RCxDecode(CipherText, 'Passwort');
  Delete(PlainText, 1, 16);
end;
Diese Vorgehensweise bettet den Zufallswert IN die Verschlüsselung ein. Das ist eingewaltiger Unterschied zu den Init Vektoren bei normalen Blockverschlüsselungen. Diese IV's sind nämlich in der CipherText Nachricht 1 zu 1 lesebar gespeichert, also nur äußere Merkmale.

Gruß Hagen
Angehängte Dateien
Dateityp: pas rcx_159.pas (5,6 KB, 613x aufgerufen)
»Mein Kaffee ist so schwarz — der fängt gleich an zu rappen...«
  Mit Zitat antworten Zitat
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 21:24 Uhr.
Powered by vBulletin® Copyright ©2000 - 2019, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2019 by Daniel R. Wolf