|
Antwort |
Registriert seit: 2. Okt 2003 Ort: Hamburg 548 Beiträge Delphi 2005 Professional |
#1
RC4 und RCx Stromdekorierer
Die TRC?StreamDecorator klassen machen es möglich, die funktionalitat jedes beliebigen streams, um eine RC4 oder RCx (ein RC4 derivat von Hagen) verschlüsselung (siehe hagEnCode.pas und RCx.pas) zu erweitern. Wobei die erweiterung der funktionalität nicht durch eine starre ableitung realisiert wird, sondern durch das Dekorierer-Entwurfsmuster, dh. der dekorierer verpackt (wrappen) einen beliebigen stream und delegiert alle aufrufe an ihn weiter, oder modifiziert sie (lesen, schreiben etc). Die lese-und schreibaufrufe werden abgefangen und die kodierung durchgeführt. Wobei die schnittstelle nach aussen die gleiche bleibt, damit der dekorierer wie ein ganz normaler stream behandelt werden kann. Allgemeine informationen zum prinzip des dekorierers: http://de.wikipedia.org/wiki/Dekorierer In diesen stromverschlüsselungen, ist ein springen im strom nicht möglich, da sonst der aktuelle kontext nicht mehr stimmen würde und somit der output unbrauchbar wäre. Dh. bei expliziten Seek-aufrufen wird die exception ERCSeekNotAllowed geschmissen! Die RC4 kodierung von Hagen Redmann kann man hier einsehen -> HagEnCode.pas Und die allgemeine RCx-Kodierung findet man hier. Die verwendung demonstriert dann auch ganz gut die schönheit dieses konzepts:
Delphi-Quellcode:
Wobei man statt TRCxStreamDecorator auch TRC4StreamDecorator nehmen kann, wenn man eine normale, unsicherere RC4 Verschlüsselung benutzen will. Keinesfalls aber sollte man TRCStreamDecorator benutzen, denn diese Klasse ist abstrakt!
uses RCStreamDeco;
... procedure TForm1.SaveBuClick(Sender: TObject); var Stream:TRCxStreamDecorator; begin // variante 1 der Erzeugung des RCx-Stream-Dekorierers // und des eigentlichen streams. // Der RCx-stream verhalt sich nun wie ein fileStream, nur // dass er eben verschlüsseln kann, wenn er will (EnCodeMode). stream := TRCxStreamDecorator.Create(TFileStream.Create(Filename, fmCreate)); with Stream do try // Da wir explizit mit TRCxStreamDecorator zu tun haben, // konnen wir das Passwort, welches zum Erstellen der SandBox benutzt wird, // nachträglich setzen. Password := 'Password'; // Zufällige Zeichenfolge (salt) schreiben, damit der restliche codierte // Text, bei jeder Verschlüsselung andere Resultate ergibt. // Nur beim RCx verfugbar. WriteSalt; // RC4 liefert immer, bei gleichem Text, gleiche Resultate. // Memo1 kodieren und in Datei speichern! Memo1.Lines.SaveToStream(Stream); finally // Wenn der Parameter des konstruktors 'OwnsStream' auf true ist (default) // dann erlauben es die Besitzverhältnisse, dass der Dekorierer den // FileStream selbstständig freigibt. Stream.Free; end; end; procedure TForm1.LoadBuClick(Sender: TObject); var Stream:TStream; begin // Variante 2 der Erzeugung des RCx-Stream-Dekorierers // und des eigentlichen Streams. // Hier arbeiten wir allgemein mit einem TStream und wissen später nicht, // um was für einen Stream es sich handelt. Deshalb müssen alle nötigen // Informationen schon im Konstruktor mitgegeben werden. stream := TRCxStreamDecorator.Create( TFileStream.Create(fileName, fmOpenRead), // der konkrete stream true, // ownsStream (auto-free) 'Password' // Passwort fur die SandBox emEncodeWriting ); // schreibend kodieren try // hier noch das 'salt' lesen, um es zu entfernen. // Wird versucht es an einer falschen Stelle zu lesen, so // wird eine 'EInvalidDecryption' geworfen (Stream as TRCxStreamDecorator).ReadSalt; // wir casten hier nur, weil der Stream allgemein ist. // in diesem Fall würde sich eine Lösung wie bei WriteBuClick anbieten. // Daten aus datei laden ins Memo1 laden und dabei dekodieren! Memo1.Lines.LoadFromStream(Stream); finally // Wenn der Parameter des Konstruktors 'OwnsStream' auf true ist (default) // dann erlauben es die Besitzverhaltnisse, dass der Dekorierer den // FileStream selbstständig freigibt. Andernfalls musste man sich selbst // darum kummmern Stream.Free; end; end; Genaue Erläuterungen über RCx entnehme man bitte Hagens Anmerkungen. Der Unit
Delphi-Quellcode:
unit RCStreamDeco;
// written by maximov 19.02.2005 // Die TRC?StreamDecorator Klassen machen es möglich, die Funktionalitat jedes // beliebigen Streams, um eine RC4 oder RCx (ein RC4 derivat von Hagen) // Verschlüsselung (siehe hagEnCode.pas und RCx.pas) zu // erweitern. Wobei die Erweiterung der Funktionalitat nicht durch eine starre // Ableitung realisiert wird, sondern durch das Dekorierer-Entwurfsmuster, // dh. der Dekorierer verpackt (wrappen) einen beliebigen Stream und delegiert // alle Aufrufe an ihn weiter, oder modifiziert sie (lesen, schreiben). // Die Lese-und Schreibaufrufe werden abgefangen und die Kodierung durchgefuhrt. // Wobei die Schnittstelle nach außsen die gleiche bleibt, damit der Dekorierer wie // ein ganz normaler Stream behandelt werden kann. // Allgemeine informationen zum Prinzip des Dekorierers: // [url]http://de.wikipedia.org/wiki/Dekorierer[/url] // In diesen Stromverschlüsselungen, ist ein Springen im Strom nicht moglich, // da sonst der aktuelle Kontext nicht mehr stimmen würde und somit der Output // unbrauchbar ware. Dh. bei expliziten Seek aufrufen wird die Exception // ERCSeekNotAllowed geschmissen! // Die RC4 Kodierung von Hagen Redmann kann man hier einsehen -> HagEnCode.pas // [url]http://www.delphipraxis.net/topic30830_rc4verschluesselung.html[/url] // 20.02.2005 - Veröffentlichung! // 21.02.2005 - Seek Exception, um im richtigen Kontext zu bleiben. // 21.02.2005 - Temp-Buffer in Read entfernt. // 25.02.2005 - Abstrakte Oberklasse geschaffen. // 25.02.2005 - Hangens RC4 derivat RCx integriert. interface uses classes, hagEnCode, RCx, sysUtils; type ERCSeekNotAllowed = class(Exception); EInvalidDecryption = class(Exception); TEncodeMode = (emEncodeWriting, emEncodeReading); TRCStreamDecorator = class(TStream) private FStream:TStream; FOwnsStream:boolean; FEncodeMode:TEncodeMode; protected function GetSize: Int64; override; procedure SetSize(const NewSize: Int64); overload; override; procedure SetSize(NewSize: Longint); overload; override; procedure Encode(const source; var dest; Count:integer); virtual; abstract; procedure Decode(const source; var dest; Count:integer); virtual; abstract; procedure SetPassword(const Value: string); virtual; abstract; public constructor Create(aStream:TStream; OwnsStream:boolean = true); overload; constructor Create(aStream:TStream; OwnsStream:boolean; const aPassword:string; theEncodeMode:TEncodeMode = emEncodeWriting); overload; destructor Destroy; override; function Write(const Buffer; Count: Integer): Integer; override; function Read(var Buffer; Count: Integer): Integer; override; function Seek(Offset: Integer; Origin: Word): Integer; overload; override; function Seek(const Offset: Int64; Origin: TSeekOrigin): Int64; overload; override; property Password:string write SetPassword; property EncodeMode:TEncodeMode read FEncodeMode write FEncodeMode; end; TRC4StreamDecorator = class(TRCStreamDecorator) private FRC4:TRC4Context; procedure SetSandbox(const Value: TRC4Context); protected procedure Encode(const source; var dest; Count: Integer); override; procedure Decode(const source; var dest; Count: Integer); override; procedure SetPassword(const Value: String); override; public destructor Destroy; override; property Sandbox:TRC4Context write SetSandbox; end; TRCxStreamDecorator = class(TRCStreamDecorator) private FRCx:TRCxContext; procedure SetSandbox(const Value: TRCxContext); protected procedure Encode(const source; var dest; Count: Integer); override; procedure Decode(const source; var dest; Count: Integer); override; procedure SetPassword(const Value: String); override; public destructor Destroy; override; procedure WriteSalt(Size: Byte = 16); procedure ReadSalt; property Sandbox:TRCxContext write SetSandbox; end; implementation procedure ProtectString(var Value: String); begin FillChar(Pointer(Value)^, Length(Value), 0); end; function Checksum(const Value: String): Byte; var I: Integer; begin Result := 0; for I := 1 to Length(Value) do Inc(Result, Result xor Ord(Value[I])); end; { TRCStreamDecorator } constructor TRCStreamDecorator.Create(aStream: TStream; OwnsStream:boolean; const aPassword:string; theEncodeMode:TEncodeMode = emEncodeWriting); begin Create(aStream, OwnsStream); Password := aPassword; EncodeMode := theEncodeMode; end; constructor TRCStreamDecorator.Create(aStream: TStream; OwnsStream: boolean); begin Assert(assigned(aStream),'The decorated stream is not assigned'); FStream := aStream; FOwnsStream := OwnsStream; FEncodeMode := emEncodeWriting; end; destructor TRCStreamDecorator.Destroy; begin if FOwnsStream then FStream.Free; FStream := nil; inherited; end; function TRCStreamDecorator.Read(var Buffer; Count: Integer): Integer; begin result := FStream.Read(Buffer, count); case EncodeMode of emEncodeWriting: Decode(Buffer, Buffer, Result); // abstrakter aufruf emEncodeReading: Encode(Buffer, Buffer, Result); // abstrakter aufruf end; end; function TRCStreamDecorator.Write(const Buffer; Count: Integer): Integer; var temp:pointer; begin GetMem(temp, count); case EncodeMode of emEncodeWriting: Encode(Buffer, temp^, Count); // abstrakter aufruf emEncodeReading: Decode(Buffer, temp^, Count); // abstrakter aufruf end; result := FStream.Write(temp^, count); FreeMem(temp, count); end; function TRCStreamDecorator.GetSize: Int64; begin result := FStream.Size; end; procedure TRCStreamDecorator.SetSize(const NewSize: Int64); begin FStream.Size := NewSize; end; procedure TRCStreamDecorator.SetSize(NewSize: Integer); begin FStream.Size := NewSize; end; function TRCStreamDecorator.Seek(Offset: Integer; Origin: Word): Integer; begin result := Seek(Int64(Offset), TSeekOrigin(Origin)); end; function TRCStreamDecorator.Seek(const Offset: Int64; Origin: TSeekOrigin): Int64; begin if (Origin = soCurrent) and (Offset = 0) then Result := FStream.Seek(Offset, Origin) else raise ERCSeekNotAllowed.Create('Seeking is not allowed'); end; { TRC4StreamDecorator } destructor TRC4StreamDecorator.Destroy; begin RC4Done(FRC4); inherited; end; procedure TRC4StreamDecorator.Encode(const source; var dest; Count: Integer); begin RC4Code(FRC4, source, dest, Count); end; procedure TRC4StreamDecorator.Decode(const source; var dest; Count: Integer); begin RC4Code(FRC4, source, dest, Count); end; procedure TRC4StreamDecorator.SetPassword(const Value: String); begin RC4Init(FRC4,Value); end; procedure TRC4StreamDecorator.SetSandbox(const Value: TRC4Context); begin FRC4 := Value; end; { TRCxStreamDecorator } destructor TRCxStreamDecorator.Destroy; begin RCxDone(FRCx); inherited; end; procedure TRCxStreamDecorator.Encode(const source; var dest; Count: Integer); begin RCxEncode(FRCx, source, dest, Count); end; procedure TRCxStreamDecorator.Decode(const source; var dest; Count: Integer); begin RCxDecode(FRCx, source, dest, Count); end; procedure TRCxStreamDecorator.SetPassword(const Value: String); begin RCxInit(FRCx, Value); end; procedure TRCxStreamDecorator.SetSandbox(const Value: TRCxContext); begin FRCx := Value; end; procedure TRCxStreamDecorator.WriteSalt(Size: Byte = 16); var Salt: String; CRC: Byte; begin Salt := RCxRandomString(Size); try WriteBuffer(Size, SizeOf(Size)); WriteBuffer(Pointer(Salt)^, Size); CRC := Checksum(Salt); WriteBuffer(CRC, SizeOf(CRC)); finally ProtectString(Salt); end; end; procedure TRCxStreamDecorator.ReadSalt; var Salt: String; CRC,Size: Byte; begin ReadBuffer(Size, SizeOf(Size)); SetLength(Salt, Size); try ReadBuffer(Pointer(Salt)^, Size); ReadBuffer(CRC, SizeOf(CRC)); if CRC <> Checksum(Salt) then raise EInvalidDecryption.Create('Invalid decryption'); finally ProtectString(Salt); end; end; end. Bitte sagt mir was ihr davon haltet oder ob ihr damit was anfangen könnt. Und dank an Hagen für die Kodierung und die Optimierungen. [edit=Chakotay1308]Neue Version des Eintrages eingefügt. Mfg, Chakotay1308[/edit] [edit=Chakotay1308]Anhang geupdatet. Mfg, Chakotay1308[/edit] [edit=Chakotay1308]Einige Anpassungen. Mfg, Chakotay1308[/edit] [edit=Matze]Zig Rechtschreibfehler behoben und Code korrekt formatiert. Mfg, Matze[/edit]
mâxîmôv.
{KDT} |
Zitat |
Registriert seit: 21. Jul 2002 Ort: Bonn 5.403 Beiträge Turbo Delphi für Win32 |
#2
Von maximov kommt noch folgende Erweiterung:
Mit dem RC-Stromdekorierer INIs verschlüsseln betreff: RC4 Stromdekorierer Kürzlich erhielt ich dazu folgende frage...
Zitat von Jolomino:
hallo,
habe mir mal deinen post angeschaut, das dekodieren und kodieren funzt auch ganz wunderbar. aber könntest du mir evtl. verraten, wie ich dieses auf einer ini-datei anwende? bekomme es leider nicht hin. oder ist es womöglich überhaupt nicht auf ini´s anwendbar... Die antwort: Hallo jolomino, normalerweise wäre dein vorhaben nicht möglich, da TIniFile kein stream ist. Der dekorator braucht aber nunmal ein stream, den er umschliessen kann. Allerdings gibt es die klasse TMemIniFile, welche für das speichern Stringlisten verwendet, die man dann verschlüsseln kann. Also machen wir eine neue klasse. Allerdings müssen dafür einige methoden ersetzt werden. LoadValue zb. ist nicht virtuell und kann daher nicht überschrieben werden, also Kann man einfach die stellen ersetzen wo loadValue aufgerufen wird und dann das neue LoadValue aufrufen. In demfall müssen also Create und Rename ersetzwerden. UpdateFile ist virtuell und kann überschrieben werden, ohne es zu vererben. WICHTIG: die RCx klasse von hagen wird auch benötigt. Also hier die klasse:
Delphi-Quellcode:
Musst halt nur updateFile selbst aufrufen! Aber ansonsten hast du somit eine verschlüsselte ini-Datei. Wenn du willst kannst du unit auch gerne in der codeLib veröffentlichen, damit vielleicht auch andere was davon haben.// RCx inifile unit. // written by maximov (max hue) 2005. // Inspiration by Jolomino. // free for all, without warrenty. // 12.04.2005 - fixes unit RCmxIni; interface uses inifiles; type TRCxIniFile = class(TMemIniFile) private FFileName:string; FPassword:string; procedure LoadValues; protected public constructor Create(const FileName, PassWord: string); procedure UpdateFile; override; procedure Rename(const FileName: string; Reload: Boolean); destructor Destroy; override; end; implementation uses classes, RCStreamDeco, sysUtils; constructor TRCxIniFile.Create(const FileName, PassWord: string); begin FFileName := FileName; FPassWord := PassWord; // instance sauber erzeugen, aber durch '' keine values laden inherited Create(''); // neues loadValue eingeführt, mit RCx LoadValues; end; destructor TRCxIniFile.Destroy; begin FPassword := ''; inherited; end; procedure TRCxIniFile.Rename(const FileName: string; Reload: Boolean); begin FFileName := FileName; if Reload then LoadValues; end; procedure TRCxIniFile.LoadValues; var List: TStringList; rcxStream:TRCxStreamDecorator; begin if (FFileName <> '') and FileExists(FFileName) then begin List := TStringList.Create; try // Filestream, von RCx-dekorierer gewrappt, erzeugen. rcxStream := TRCxStreamDecorator.Create( TFileStream.Create(FFileName, fmOpenRead or fmShareDenyNone), true, FPassword); try // salz lesen -> zur besseren sicherheit rcxStream.ReadSalt; // entschlüsselnd laden List.LoadFromStream(rcxStream); SetStrings(List); finally rcxStream.Free; end; finally List.Free; end; end else Clear; end; procedure TRCxIniFile.UpdateFile; var List: TStringList; rcxStream:TRCxStreamDecorator; begin List := TStringList.Create; try // stream erzeugen. rcxStream := TRCxStreamDecorator.Create( TFileStream.Create(FFileName, fmCreate), true, FPassword); try GetStrings(List); // salz mit zufälliger länge schreiben -> erhöht die sicherheit rcxStream.WriteSalt(16 + random(32)); List.SaveToStream(rcxStream); finally rcxStream.Free; end; finally List.Free; end; end; end. Viel spass damit und wenn fragen sind, immer her damit. grüsse maximov. Edit: Kleine verbesserungen von Hagen eingebaut. Danke! [edit=Chakotay1308]SID aus Link entfernt. Mfg, Chakotay1308[/edit] |
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 |