Einzelnen Beitrag anzeigen

Benutzerbild von negaH
negaH

Registriert seit: 25. Jun 2003
Ort: Thüringen
2.950 Beiträge
 
#2

Re: einzelne Zeichenkette mit DEC 5.1 verschlüsseln

  Alt 18. Feb 2008, 12:05
Den Sessionkey lieferst du niemals mit, dann könnte ich ja meinen Tresor gleich offen stehen lassen.

Den Salt der zur Erzeugung des Sessionkeys dient den musst du immer mitliefern. Das bedeutet das dein verschlüsselter String um zb. 16 Bytes länger wird als der unverschlüsselte String. Diese Expansion ist der Salt. Du kannst den Salt speichern wie du möchtest, bewährt hat es sich diesen am Anfang der Daten zu speichern. Diese Expansion wirst du so oder so haben müssen, wenn es sicher sein soll.

Du kannst im einfachsten Falle ausgehend von den TStream basierten Funktionen eine spezielle Funktion für deine Strings bauen. Dazu gehst du den Umweg über einen TMemoryStream. Oder du adaptierst die gleiche Methode und arbeitest direkt auf den Speicherdaten. Dann benutzt man zb. .EncodeBinary() oder .Encode().

Zb.

Delphi-Quellcode:
function Encrypt(const Value: String; const Password: String): String;
var
  Salt,SessionKey: Binary;
begin
  Salt := RandomBinary(16);
  with TCipher_XYZ.Create do
  try
    SessionKey := THash_XYZ.KDF(Password, Salt, Context.MaxKeySize, TFormat_Copy);
    Mode := cmCFS8; // ein 8Bit Feedback Modus ist für kurze Datenmengen sicherer
    Init(SessionKey);
    Result := TFormat_MIME64.Encode(Salt + EncodeBinary(Value, TFormat_Copy));
  finally
    Free;
    ProtectBinary(Salt);
    ProtectBinary(SessionKey);
  end;
end;
Als Ausgabe dann einen INet-MIME Base64 kodierter Wert. In den ersten 16 Bytes der Salt und nachfolgend die verschlüsselten Daten. Bei der Entschlüsselung also erst aus dem MIME64 Format umwanden nach Binär dann Salt extrahieren, mit KDF Sessionkey berechnen und Daten entschlüsseln.

Delphi-Quellcode:
function Decrypt(const Value: String; const Passwod: String; String;
begin
  with TCipher_XYZ.Create do
  try
    Result := TFormat_MIME64.Decode(Value);
    SessionKey := THash_XYZ.KDF(Password, Copy(Result, 1, 16), Context.MaxKeySize, TFormat_COPY);
    Mode := cmCFS8;
    Init(SessionKey);
    
    Decode(Result[17], Result[1], Length(Result) -16); // inplaced Entschlüsselung
    SetLength(Result, Length(Result) -16);
  finally
    Free;
    ProtectBinary(SessionKey);
  end;
end;
Die Umwandlung in das MIME64 Format ist vorteilhaft, da man so binäre Daten lesbar speichern kann. Der Nachteil ist halt das der MIME64 String eben wiederum im Verhältnis 3 zu 4 Bytes länger wird als der originale String.

Der Mode cmCFS8 ist prohibitär und von mir entwickelt. Abgeleit vom CBC8 -> Cipher Block Chaining mit 8 Bit Feedback (ist Standard), arbeitet der CFS8 im ersten Schritt identisch, verknüpft aber zusätzlich noch den verschlüsselten Output per XOR Operation mit dem internen Feedback Register. Damit kann man sich den CFS8 so vorstellen wie einen übereinandergelegten doppelten CBC, so ähnlich wie die Schindeln eines Daches. Damit ist der CFS8 Modus eine Alles-oder-Nichts Verschlüsselung. Ändert sich ein Bit in den verschlüsselten Daten so ist die komplette Entschlüsselung danach fehlerhaft. Somit höhere kryptographische Sicherheit, aber dafür keine technologische Selbsynchronisation bei der Übertragung fehlerhafter Daten. Für kurze Strings, meistens Passwörter oder andere sehr wichtige Daten, ist das eine gute Wahl.

Gruß Hagen

EDIT: Link auf angesprochenen Thread http://www.delphipraxis.net/internal...882&highlight=
macht die Sache einfacher für Mitleser.
  Mit Zitat antworten Zitat