Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Verschlüssel, in einer .ini-Datei speichern später auflösen (https://www.delphipraxis.net/22900-verschluessel-einer-ini-datei-speichern-spaeter-aufloesen.html)

Lamy 25. Mai 2004 21:25


Verschlüssel, in einer .ini-Datei speichern später auflösen
 
Hi!

Ich möchte hier gerne Passwörter in einer .ini-Datei speichern, hier mal der Code:

Code:
PROCEDURE TVerbindung.CbHostnameChange(Sender: TObject);
VAR ini: Tinifile;
  s: STRING[255];
  c: ARRAY[0..255] OF byte ABSOLUTE s;
  i: Integer;
BEGIN
  ini := TIniFile.Create(PChar(ExtractFilePath(Application.ExeName) + '\history.ini'));
  s := ini.Readstring(Cbhostname.text, 'Passwort', s);
        For i := 1 To Length(s) do s[i] := Chr(superkey[i] Xor ord(s[i]));
  Edpasswort.Text := s;
  Edusername.text := ini.Readstring(Cbhostname.text, 'Username', Edusername.Text);
  EdPort.text := ini.Readstring(Cbhostname.text, 'Port', EdPort.Text);
  ini.free;
END;
Verschlüsselt wurde das so:

Code:
PROCEDURE TVerbindung.BtverbindungClick(Sender: TObject);
VAR ini: Tinifile;
////////////////
  s: STRING[255];
  c: ARRAY[0..255] OF byte ABSOLUTE s;
  i: Integer;
////////////////
BEGIN
(...)
  s := EdPasswort.Text;
  FOR i := 1 TO ord(s[0]) DO
    c[i] := superkey[i] XOR c[i];
  ini.Writestring(CbHostname.Text, 'Passwort', s);
(...)
Was ist daran falsch?
Es wird zwar ent- aber nicht wieder verschlüsselt.

Danke schonmal für eure Hilfe!

negaH 25. Mai 2004 21:32

Re: Verschlüssel, in einer .ini-Datei speichern später auflö
 
ok, eliminieren wir mal den Code der keinerlei Wirkung besitzt dann wird aus:

Delphi-Quellcode:

  s := EdPasswort.Text;
  FOR i := 1 TO ord(s[0]) DO
    c[i] := superkey[i] XOR c[i];
  ini.Writestring(CbHostname.Text, 'Passwort', s);
eben

Delphi-Quellcode:
  s := EdPasswort.Text;
  ini.Writestring(CbHostname.Text, 'Passwort', s);
und daraus

Delphi-Quellcode:
  ini.Writestring(CbHostname.Text, 'Passwort', EdPasswort.Text);
Gruß Hagen

Lamy 25. Mai 2004 21:40

Re: Verschlüssel, in einer .ini-Datei speichern später auflö
 
Hab den Code aus dem Delphi6 - Kochbuch, dort steht er (fast) genau so geschrieben, natürlich wird noch was anderes deklariert und hinzugefügt:

Delphi-Quellcode:
(...)
CONST keysize = 1000; { hier kann die Größe des Schlüssels geändert werden }
  code = 4711; { der presönliche Schlüssel (Longint-Wert möglich) }

VAR
  Verbindung: TVerbindung;
  superkey: ARRAY[1..keysize] OF byte;

(...)
PROCEDURE TVerbindung.FormCreate(Sender: TObject);
VAR ini: Tinifile;
  i: integer;
BEGIN
  randseed := code;
  randomize;
  FOR i := 1 TO high(superkey) DO
    superkey[i] := random(255);
(...)

negaH 25. Mai 2004 21:48

Re: Verschlüssel, in einer .ini-Datei speichern später auflö
 
Sorry, ich habe den nachfolgenden TypCast übersehen

Delphi-Quellcode:
var
 c: ARRAY[0..255] OF byte ABSOLUTE s;
Sieht man sehr selten heutzutage.

Dein Problem entsteht aber dadurch das durch die XOR Operation im String selber unlesbare Sonderzeichen entstehen, und INI Files können diese NICHT korrekt speichern.

Gruß Hagen

Lamy 25. Mai 2004 22:10

Re: Verschlüssel, in einer .ini-Datei speichern später auflö
 
Na doll - gibts ne Alternative?
[bitte nix in der Registry speichern :/

negaH 25. Mai 2004 22:13

Re: Verschlüssel, in einer .ini-Datei speichern später auflö
 
Jo, machdem der Text "verschlüsselt" wurde wird er in ein lesbares Format umgewandelt und dann gespeichert.
Oder du benutzt unter Delphi 7 TIniFile.WriteBinary(), diese Methode kann x-beliebige binäre Streams speichern indem sie diese Daten in der INI als HEX Werte speichert.

Gruß Hagen

negaH 25. Mai 2004 22:19

Re: Verschlüssel, in einer .ini-Datei speichern später auflö
 
Übrigens, deine "Verschlüsselung" ist ziemlich unsicher und könnte unter Umständen in neueren Delphi Versionen unterschiedliche Resultate erzeugen. Denn Borland hat schon immer proklamiert das der Zufallsgenerator in Random() sich von Version zu Version unterscheiden kann.

Wenn du es echt einfach haben willst das könntest du auch das DEC benutzen:


Delphi-Quellcode:

procedure SavePassword;
begin
  Ini.WriteString(,...., THash_MD5.CalcString('Secret Key' + EPassword.Text, nil, fmtMIME64));
end;

function CheckPassword: Boolean;
begin
  Result := Ini.ReadString(...., '') = THash_MD5.CalcString('Secret Key' + EPasword.Text, fmtMIME64);
end;
Auf alle Fälle wäre dies "sicherer" als deine Methode.

Was soll denn eigentlich passieren wenn der Benutzer so clever ist und in der INI Datei einfach verschiedene Passwörter austauscht ??


Gruß Hagen

Lamy 25. Mai 2004 23:42

Re: Verschlüssel, in einer .ini-Datei speichern später auflö
 
... Dann kann er ganz einfach nicht zum Ftpserver connecten und eine Meldung wird angezeigt dass das PW falsch ist :)
Hab leider nur Delphi 5...


Braucht man echt nicht mehr als nur diese eine Prozedur und die Funktion? Das wär zu einfach ^^

Gute Nacht,
Lamy

Matze 26. Mai 2004 06:59

Re: Verschlüssel, in einer .ini-Datei speichern später auflö
 
Zitat:

Zitat von Lamy
Braucht man echt nicht mehr als nur diese eine Prozedur und die Funktion? Das wär zu einfach ^^

Falls du das DEC benutzen möchtest, brauchst du natürlich schon noch ein bisschen mehr. ;)

Hier kannst du es herunterladen.
Falls du es nicht weißt, das DEC ist von Hagen Reddmann (negaH). ;) Also von dem, der dir bis jetzt so schön geholfen hat. ;)

negaH 26. Mai 2004 10:39

Re: Verschlüssel, in einer .ini-Datei speichern später auflö
 
Zitat:

... Dann kann er ganz einfach nicht zum Ftpserver connecten und eine Meldung wird angezeigt dass das PW falsch ist
Hab leider nur Delphi 5...
Aha, schon hat sich deine Frage wieder ein bischen präzesiert :)
Du benötigst also kein LogIn sondern eine Passwortsicherung mit Wiederherstellung des originalen Passwortes.

Dazu ist obige Routine natürlich nicht benutzbar, ein gutes Zeichen, da man in der Kryptographie IMMER nur die Algos. auf ein Problem anwenden sollte die für dieses Problem entwickelt wurden.
Im Falle eines Logins wäre eine erweiteret Methode wie die obige also richtig.

Nun, in deiner Software soll das Login Passwort für einen FTP Server gespeichert werden. Ich vermute mal das deinen Software für einen Benutzer viele solcher Zugangs Kennwörter zu vielen Servern speichern soll. Am besten ist dann folgendes Konzept:

Es gibt eine Konfigurationsdatei in der jeder FTP Server, dessen Einstellungen, URL und eben Login Password und Username verschlüsselt gespeichert werden. Wichtig ist dabei das alle Informationen verschlüsselt werden, da alleine die Infos welche FTP Server ein Benutzer ansteuert schon ein Datenschutzproblem darstellen.

Diese Konfigurationsdatei ist verschlüsselt, und das mit einem Passwort das der jeweilige Benutzer beim Starten in Deine Software eingeben muß. Aus Sicht dieser Forderungen ist es beweisbar möglich das komplette System kryptographisch sicher zu bekommen.

Fazit:
- baue die kompletten Konfigurationen der FTP Server in Records oder Objecte
- speichere die komplette Liste in einen TMemoryStream
- verschlüssele diesen Stream mit einem sicheren Verschlüsselungsalgo. zb. TCipher_Blowfish oder TCipher_Rijndael aus dem DEC. Als Passwort wird das Anmelde-Passwort des Benutzers genommen.
- Speichere den verschlüsselten Stream als Datei, oder in der Registry.

- der spätere Login eines benutzers kann nun leicht überprüft werden. Die Konfiguration wird geladen und mit dem eingegeben Passwort entschlüsselt. Sollte eine Prüfsumme damit korrekt entschlüsselt worden sein, so war das eingegeben Passwort korrekt und die Software erlaubt den Zugriff durch den Benutzer.

Die komplette Sicherheit des Systems verankert sich im benutzergewähltem Passwort. Nur eine Brute Force Attacke wäre möglich um das Passwort zu knacken. Ist das Benutzerpasswort schlecht gewählt so hast du zumindestens alle kryptographisch notwendigen Optionen ausgereizt, denn mehr geht nicht.

Falls du weitere Fragen hast wie man am besten die Daten in solchen Dateien verschlüsselt dann frag.

Gruß Hagen

PS: das was du also programmieren willst ist ein sogenannter "Passwordsafe" ;)

Lamy 26. Mai 2004 12:57

Re: Verschlüssel, in einer .ini-Datei speichern später auflö
 
Waaahh!

Ich wollte doch nur verhindern, dass jemand die .ini - Datei öffnet und der dann sofort das Passwort ablesen kann - nicht sowas kompliziertes was ich eh nicht versteh :pale: :|
Kann man dafür nicht einfach den Algorithmus nehmen, um das ganze einfach in die .ini-Datei zu schreiben?
Soll ja nix profesionelles werden sondern einfach mal ein Projekt um mich mit Delphi vertraut zu machen...
Vielen Dank bisher!

Lamy

Steve 26. Mai 2004 13:07

Re: Verschlüssel, in einer .ini-Datei speichern später auflö
 
Zitat:

Zitat von Lamy
Ich wollte doch nur verhindern, dass jemand die .ini - Datei öffnet und der dann sofort das Passwort ablesen kann

Versuchs mal damit, da sind einige Verschlüsselungsalgorithmen schon umgesetzt und ganz easy anwendbar: TurboPower LockBox

Gruß
Stephan

shmia 26. Mai 2004 13:27

Re: Verschlüssel, in einer .ini-Datei speichern später auflö
 
Na dann werde ich hier auch mal meinen Senf dazugeben. :mrgreen:

1.) die Verschlüsselung muss von der Speicherung getrennt werden, damit jeder Teil
für sich getest werden kann. Die beiden Dinge dürfen nicht vermischt werden.

2.) ich zeige hier mal eine ganz einfache Verschlüsselung, die mit XOR arbeitet
und somit ver- als auch entschlüsseln kann:
Delphi-Quellcode:
function SimpleCryptString(const S, Key: string): string;
var
  i, j: Integer;
  C: Byte;
  P: PByte;
begin
  SetLength(Result, Length(S));
  P := PByte(Result);

  j := 1;
  for i := 1 to Length(S) do
  begin
    C := Ord(S[i]);

    C := C xor Ord(Key[j]);
    P^ := C;
    Inc(P);
    Inc(j);
    if j > Length(Key) then
      j := 1;
  end;
end;
3. Bei der Verschlüsselung entstehen Zeichen, die nicht in einer Inidatei gespeichert
werden können. Deshalb muss man das verschlüsselte Passwort codieren.
Die einfachste Methode ist die hexadezimale Codierung: jedes Zeichen wird zu 2 Hexziffern codiert.
Dazu folgende Funktionen:
Delphi-Quellcode:
function StringToHexStr(const value:string):string;
begin
   SetLength(Result, Length(value)*2); // es wird doppelter Platz benötigt
   if Length(value) > 0 then
      BinToHex(PChar(value), PChar(Result), Length(value));
end;

function HexStrToString(const value:string):string;
begin
   SetLength(Result, Length(value) div 2); // es wird halber Platz benötigt
   if Length(value) > 0 then
      HexToBin(PChar(value), PChar(Result), Length(value));
end;
Alternativ kann man auch noch die Base64-Codierung (auch als Mimekodierung bekannt) verwenden.

4.) Damit entsteht folgender Pseudocode:
Delphi-Quellcode:
   PWverschl := SimpleCryptString(PWKlartext, Supperkey); // verschlüsseln
   PWverschl := StringToHexStr(PWverschl);    // Codieren
   SaveSettings(ftpserver, user, PWverschl, directory);

negaH 26. Mai 2004 13:39

Re: Verschlüssel, in einer .ini-Datei speichern später auflö
 
Wo ist das Problem ?

Delphi-Quellcode:

uses DECUtil, Cipher;

function Encode(const Value, Password: String): String;
begin
  with TCipher_Rijndael.Create(Password, nil) do
  try
    Result := CodeString(Value, paEncode, fmtMIME64);
  finally
    Free;
  end;
end;

function Decode(const Value, Password: String): String;
begin
  with TCipher_Rijndael.Create(Password, nil) do
  try
    Result := CodeString(Value, paDecode, fmtMIME64);
  finally
    Free;
  end;
end;
Wie einfacher soll es denn noch gehen ??

Gruß Hagen

PS: auf alle Fälle ist dies sicherer als alle anderen genannten Beispiele.
PPS: LockBox ist schön und gut, aber nicht unbedingt einfacher und eben sicherer. Hier im Forum hatte ich dies schon mal ausführlich erklärt warum dies so sein muß.

negaH 26. Mai 2004 14:06

Re: Verschlüssel, in einer .ini-Datei speichern später auflö
 
Falls du auf's DEC verzichten willst so kann man eben auch mit nur ein wenig mehr Source dein Problem wesentlich sicherer lösen. Nachfolgend ein Source der den bekannten RC4 Algorithmus als Stand Alone implementiert. Man erkennt das für eine sichere Verschlüsselung nicht viel mehr Code benötigt wird als für eine unsicherer XOR Verschlüsselung.

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,U: Byte;
  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 := 1;
    for S := 0 to 255 do
    begin
      Inc(R, D[S] + Ord(Key[U]));
      T   := D[S];
      D[S] := D[R];
      D[R] := T;
      Inc(U);
      if U > L then U := 1;
    end;
  end;
end;

procedure RC4Code(var RC4: TRC4Context; const Source; var Dest; Count: Integer); overload;
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;

function RC4Code(const Value, Password: String): String; overload;
var
  RC4: TRC4Context;
  Len: Integer;
begin
  RC4Init(RC4, Password);
  try
    Len := Length(Value);
    SetLength(Result, Len);
    RC4Code(RC4, Value[1], Result[1], Len);
  finally
    RC4Done(RC4);
  end;
end;

function BinToHexStr(const Value: String): String;
var
  Size: Integer;
begin
  Size := Length(Value);
  SetLength(Result, Size * 2);
  BinToHex(PChar(Value), PChar(Result), Size);
end;

function HexToBinStr(const Value: String): String;
var
  Size: Integer;
begin
  Size := (Length(Value) +1) div 2;
  SetLength(Result, Size);
  HexToBin(PChar(Value), PChar(Result), Size);
end;

function Encode(const Value, Password: String): String;
begin
  Result := BinToHexStr(RC4Code(Value, Pasword));
end;

function Decode(const Value, Password: String): String;
begin
  Result := RC4Code(HexToBinStr(Value), Password);
end;
Du rufst nun Encode() und respektive Decode() auf.

Gruß Hagen

[EDIT] Fehler im Source beseitigt !, hagen [/EDIT]

Lamy 26. Mai 2004 15:43

Re: Verschlüssel, in einer .ini-Datei speichern später auflö
 
Hey, danke!

Ist der Rc4 - Algorithmus auch in einer Komponente / Unit vorhanden die man vorher implementieren muss?

negaH 26. Mai 2004 16:47

Re: Verschlüssel, in einer .ini-Datei speichern später auflö
 
Hm, was für eine Frage !

RC4 kannst du aus der Netscape.EXE heraus-pfriemeln, oder als PDF Datei im WEB downloaden, oder als Unit im DEC finden, oder .. oder ... oder viel viel einfacher den obigen Code in dein Projekt kopieren.

Dieser Code wird dann in einer Unit stehen, nämlich in DEINER Unit.

Sogesehen verstehe ich entweder deine Frage nicht richtig, oder du verstehst nicht das obiger Source die komplette Lösung deines Problemes ist. Der Weg in deinen UNIT wäre dann mit der Maus von Links-Oben zu klicken, die linke Maustaste gedrückt lassen und langsam nach unten ziehen. Das macht man so lange bis der obige Source komplett blau-hinterlegt ist (abhängig von deiner Windows-Einstellung). Dann noch Srtg+C auf den eckigen Kasten mit den vielen Tasten vor dem Ding das so farbig leuchtet drücken. Nun noch deinen Source öffnen und wiederum auf dem Kasten mit den vielen tasten Strg+Einfg drücken.

Gruß Hagen

PS: sorry, aber manchmal gibt es wirklich "komische" Fragen ;)

Lamy 26. Mai 2004 17:24

Re: Verschlüssel, in einer .ini-Datei speichern später auflö
 
*duck* :oops:

Ich frag ja nur weil der RC5Init, RC5Code, usw. nicht kennt...

The-X 26. Mai 2004 17:47

Re: Verschlüssel, in einer .ini-Datei speichern später auflö
 
Ähm 1. wo steht RC5 ? :mrgreen:

2. solltest du das in eine eigene Unit verfrachten und diese mit Uses Rc4Unit; (oder ähnlich) einbinden

oder aber am anfang der Haupt-Unit einfügen damit nachfolgende Procedures/Functions das Rc4 Zeuch auf finden können (Grundlagen) :roll:

Lamy 26. Mai 2004 17:57

Re: Verschlüssel, in einer .ini-Datei speichern später auflö
 
Ach so, habs!

Danke vielmals!

:thuimb:

Lamy

negaH 26. Mai 2004 18:30

Re: Verschlüssel, in einer .ini-Datei speichern später auflö
 
Tja, RC5 soll natürlich RC4 heissen. Dies passiert wenn man mal schnell einen Code ohne Überprüfung hier im Forum entwickelt. Sorry, zZ. programmiere ich einen Mikrokontroller mit einem RC5 Infrarot Code einer Fenrbedienung, daher der Verwechsler.

Gruß Hagen


Alle Zeitangaben in WEZ +1. Es ist jetzt 04:24 Uhr.

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