|
Antwort |
Registriert seit: 21. Jul 2002 Ort: Bonn 5.403 Beiträge Turbo Delphi für Win32 |
#1
Hagen hat hier eine Routine für eine RC4-Verschlüsselung gepostet:
Delphi-Quellcode:
maximov hat dafür eine kurzes Verwendungsbeispiel gepostet:
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;
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. |
Zitat |
Registriert seit: 2. Okt 2003 Ort: Hamburg 548 Beiträge Delphi 2005 Professional |
#2
N'abend 8)
Hier die RC4 unit (ich hoffe Hagen ist damit einverstanden):
Delphi-Quellcode:
[edit=Chakotay1308]Stream-Klasse auf Wunsch von maximov entfernt. Stattdessen sollte der RCx-Stromdekorier verwendet werden. Mfg, Chakotay1308[/edit]
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=SirThornberry]Link angepasst - Mfg, SirThornberry[/edit]
mâxîmôv.
{KDT} |
Zitat |
Registriert seit: 21. Jul 2002 Ort: Bonn 5.403 Beiträge Turbo Delphi für Win32 |
#3
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:
Um die Unterschiede zu sehen mal eine Testfunktion
{
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.
Delphi-Quellcode:
Dabei wird nur das erste Zeichen der zu verschlüsselten Nachricht um ein Zufallsbyte erweitert. Und nachfolgend der mehrfache Aufruf dieser Testfunktion:
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;
Delphi-Quellcode:
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.
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 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:
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.
begin
CipherText := RCxEncode(RCxRandomString(16) + 'Nachricht', 'Passwort'); PlainText := RCxDecode(CipherText, 'Passwort'); Delete(PlainText, 1, 16); end; Gruß Hagen |
Zitat |
Ansicht |
Linear-Darstellung |
Zur Hybrid-Darstellung wechseln |
Zur Baum-Darstellung wechseln |
ForumregelnEs 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
|
|
Nützliche Links |
Heutige Beiträge |
Sitemap |
Suchen |
Code-Library |
Wer ist online |
Alle Foren als gelesen markieren |
Gehe zu... |
LinkBack |
LinkBack URL |
About LinkBacks |