AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

[DEC] WideString ver/entschlüsseln

Ein Thema von xZise · begonnen am 1. Jan 2008 · letzter Beitrag vom 9. Jan 2008
Antwort Antwort
Seite 2 von 3     12 3      
Muetze1
(Gast)

n/a Beiträge
 
#11

Re: [DEC] WideString ver/entschlüsseln

  Alt 7. Jan 2008, 08:12
Ich weiß nicht wie der Typ Binary definiert ist, aber meine ganzen Erklärungen bezogen sich nur darauf, dass du bei folgendem Konstrukt cipher.EncodeBinary(Text) etwas beachten musst: Du übergibst damit nicht den String! Du musst hier entweder den ersten Buchstaben des Strings angeben - oder, wenn die Funktion EncodeBinary() einen Pointer entgegen nimmt, eine Typkonvertierung auf PWideChar machen.

Und deine o.g. Funktion hat noch string im Aufruf und führt damit eine Autokonvertierung beim Aufruf durch (wenn mit WideString aufgerufen).

Auch Frage ich mich gerade, woher die Methode EncodeBinary() die Länge der Binarydaten ermittelt. Diese müsstest du doch irgendwo mit angeben.
  Mit Zitat antworten Zitat
Benutzerbild von negaH
negaH

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

Re: [DEC] WideString ver/entschlüsseln

  Alt 7. Jan 2008, 10:38
Hi,

also als erstes probiere mal diese beiden Funktionen:

Delphi-Quellcode:
var
  ACipherClass: TDECCipherClass = TCipher_Blowfish;
  ACipherMode: TCipherMode = cmCFS8;
  AHashClass: TDECHashClass = THash_SHA1;
  ATextFormat: TDECFormatClass = TFormat_MIME64;
  AKDFIndex: LongWord = 1;
                            
function Encrypt(const AText: String; const APassword: String): String;
var
  ASalt: Binary;
  AData: Binary;
  APass: Binary;
begin
  with ValidCipher(ACipherClass).Create, Context do
  try
    ASalt := RandomBinary(16);
    APass := ValidHash(AHashClass).KDFx(APassword, ASalt, KeySize, TFormat_Copy, AKDFIndex);
    Mode := ACipherMode;
    Init(APass);
    AData := ASalt + EncodeBinary(AText) + CalcMAC;
    Result := ValidFormat(ATextFormat).Encode(AData);
  finally
    Free;
    ProtectBinary(ASalt);
    ProtectBinary(AData);
    ProtectBinary(APass);
  end;
end;

function Decrypt(const AText: String; const APassword: String): String;
var
  ASalt: Binary;
  AData: Binary;
  ACheck: Binary;
  APass: Binary;
  ALen: Integer;
begin
  with ValidCipher(ACipherClass).Create, Context do
  try
    ASalt := ValidFormat(ATextFormat).Decode(AText);
    ALen := Length(ASalt) -16 -BufferSize;
    AData := System.Copy(ASalt, 17, ALen);
    ACheck := System.Copy(ASalt, ALen +17, BufferSize);
    SetLength(ASalt, 16);
    APass := ValidHash(AHashClass).KDFx(APassword, ASalt, KeySize, TFormat_Copy, AKDFIndex);
    Mode := ACipherMode;
    Init(APass);
    Result := DecodeBinary(AData);
    if ACheck <> CalcMAC then
      raise Exception.Create('Invalid data');
  finally
    Free;
    ProtectBinary(ASalt);
    ProtectBinary(AData);
    ProtectBinary(ACheck);
    ProtectBinary(APass);
  end;
end;
die Konstanten kannst du an deine Bedürfnisse anpassen, also Cipher-/Hash-/Formatklasse usw.
Das ist noch nicht WideString kompatibel, erstmal wollen wir die einfach Sache zum Laufen bringen.

Gruß Hagen

Achso: der Datentyp "Binary" ist einfach ein redefinierter LongString und solll im Namen anzeigen das dieser String eben als Container für binäre Daten herhalten muß.
  Mit Zitat antworten Zitat
Benutzerbild von negaH
negaH

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

Re: [DEC] WideString ver/entschlüsseln

  Alt 7. Jan 2008, 10:57
als nächstes wandeln wir diese Funktionen in WideString Funktionen um

Delphi-Quellcode:
var
  ACipherClass: TDECCipherClass = TCipher_Rijndael;
  ACipherMode: TCipherMode = cmCBCx;
  AHashClass: TDECHashClass = THash_SHA1;
  ATextFormat: TDECFormatClass = TFormat_MIME64;
  AKDFIndex: LongWord = 1;
                            
function Encrypt(const AText: WideString; const APassword: WideString): String;
var
  ASalt: Binary;
  AData: Binary;
  APass: Binary;
begin
  with ValidCipher(ACipherClass).Create, Context do
  try
    ASalt := RandomBinary(16);
    APass := ValidHash(AHashClass).KDFx(APassword[1], Length(APassword) * 2, ASalt[1], Length(ASalt), KeySize, TFormat_Copy, AKDFIndex);
    Mode := ACipherMode;
    Init(APass);
    SetLength(AData, Length(AText) * 2);
    Encode(AText[1], AData[1], Length(AData));
    Result := ValidFormat(ATextFormat).Encode(ASalt + AData + CalcMAC);
  finally
    Free;
    ProtectBinary(ASalt);
    ProtectBinary(AData);
    ProtectBinary(APass);
  end;
end;

function Decrypt(const AText: String; const APassword: WideString): WideString;
var
  ASalt: Binary;
  AData: Binary;
  ACheck: Binary;
  APass: Binary;
  ALen: Integer;
begin
  with ValidCipher(ACipherClass).Create, Context do
  try
    ASalt := ValidFormat(ATextFormat).Decode(AText);
    ALen := Length(ASalt) -16 -BufferSize;
    AData := System.Copy(ASalt, 17, ALen);
    ACheck := System.Copy(ASalt, ALen +17, BufferSize);
    SetLength(ASalt, 16);
    APass := ValidHash(AHashClass).KDFx(APassword[1], Length(APassword) *2, ASalt[1], Length(ASalt), KeySize, TFormat_Copy, AKDFIndex);
    Mode := ACipherMode;
    Init(APass);
    Result := DecodeBinary(AData);
    if ACheck <> CalcMAC then
      raise Exception.Create('Invalid data');
  finally
    Free;
    ProtectBinary(ASalt);
    ProtectBinary(AData);
    ProtectBinary(ACheck);
    ProtectBinary(APass);
  end;
end;
Beachte dabei das das Datenformat der verschlüsselten Daten als normaler LongString verarbeitet wird, bei MIME64 Format ist dies kein Problem da dieses auf Grund des Zeichensatzes für beide Datentypen, LongString und WideString, kompatibel ist.

Gruß Hagen
  Mit Zitat antworten Zitat
Benutzerbild von negaH
negaH

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

Re: [DEC] WideString ver/entschlüsseln

  Alt 7. Jan 2008, 11:05
nun können wir die komplette Funktion als WideString Funktion umbauen. Wir deklarieren die restlichen LongStrings einfach als Widestring.

Delphi-Quellcode:
var
  ACipherClass: TDECCipherClass = TCipher_Rijndael;
  ACipherMode: TCipherMode = cmCBCx;
  AHashClass: TDECHashClass = THash_SHA1;
  ATextFormat: TDECFormatClass = TFormat_MIME64;
  AKDFIndex: LongWord = 1;
                            
function Encrypt(const AText: WideString; const APassword: WideString): WideString;
var
  ASalt: Binary;
  AData: Binary;
  APass: Binary;
begin
  with ValidCipher(ACipherClass).Create, Context do
  try
    ASalt := RandomBinary(16);
    APass := ValidHash(AHashClass).KDFx(APassword[1], Length(APassword) * 2, ASalt[1], Length(ASalt), KeySize, TFormat_Copy, AKDFIndex);
    Mode := ACipherMode;
    Init(APass);
    SetLength(AData, Length(AText) * 2);
    Encode(AText[1], AData[1], Length(AData));
    Result := ValidFormat(ATextFormat).Encode(ASalt + AData + CalcMAC);
  finally
    Free;
    ProtectBinary(ASalt);
    ProtectBinary(AData);
    ProtectBinary(APass);
  end;
end;

function Decrypt(const AText: WideString; const APassword: WideString): WideString;
var
  ASalt: Binary;
  AData: Binary;
  ACheck: Binary;
  APass: Binary;
  ALen: Integer;
begin
  with ValidCipher(ACipherClass).Create, Context do
  try
    ASalt := ValidFormat(ATextFormat).Decode(AText);
    ALen := Length(ASalt) -16 -BufferSize;
    AData := System.Copy(ASalt, 17, ALen);
    ACheck := System.Copy(ASalt, ALen +17, BufferSize);
    SetLength(ASalt, 16);
    APass := ValidHash(AHashClass).KDFx(APassword[1], Length(APassword) *2, ASalt[1], Length(ASalt), KeySize, TFormat_Copy, AKDFIndex);
    Mode := ACipherMode;
    Init(APass);
    Result := DecodeBinary(AData);
    if ACheck <> CalcMAC then
      raise Exception.Create('Invalid data');
  finally
    Free;
    ProtectBinary(ASalt);
    ProtectBinary(AData);
    ProtectBinary(ACheck);
    ProtectBinary(APass);
  end;
end;
Das macht aber im Grunde keinen Unterschied mehr, ausser das der verschlüsselte WideString doppelt soviel Speicher benötigt also sein Pendant LongString, und das intern die RTL eine Speicherkopieroperation zusätzlich benötigt um den LongString=Binary in einen WideString als Result, umwandeln zu können. Dh. diese Version der Funktionen ist langsammer und verbraucht auf Grund des WideString mehr Speicher. Die Funktionen der letzten beiden Postings sind also kompatibel zueinander.

Gruß Hagen
  Mit Zitat antworten Zitat
Benutzerbild von xZise
xZise

Registriert seit: 3. Mär 2006
Ort: Waldbronn
4.303 Beiträge
 
Delphi 2009 Professional
 
#15

Re: [DEC] WideString ver/entschlüsseln

  Alt 7. Jan 2008, 14:25
Hallo Hagen
Danke für die kleine Einführung.

Aber es gibt ein kleines Problem:
Und zwar wenn ich mit der WideString-Variante Ver- und wieder entschlüssel:
Ich bekomme zwar den Ursprungstext wieder heraus, aber dieser wird immer wieder durch "#0" aufgeteilt:
Delphi-Quellcode:
decryptedText := <Mein Widestring>
str := EncryptW(decryptedText , WideString(<Mein Password (String)>));
MessageBoxW(0, PWideChar(decryptedText), PWideChar(WideString('Titel')), MB_OK);
if DecryptW(str, WideString(frmPassword.mePasswd.Text), decryptedText) then
begin
  MessageBoxW(0, PWideChar(decryptedText), PWideChar(WideString('Titel')), MB_OK);
end;
Zu der Decrypt-Version: Ich habe die etwas umgestaltet:
Sie hat einen Var-Parameter der den String zurückgibt, und als funktionsrückgabe ob es funktioniert hat (Anstelle der Exception).
Außerdem heißt sie DecryptW, da ich jetzt zwei Versionen habe

Zuerst steht in "decryptedText" (Typus: WideString) der korrekte WideString: z.B. http://www.google.de
Wenn ich das dann mit meinen Passwort verschlüssele (Typus: String) und das ergebnis wieder entschlüsselte steht in "decryptedText" zwar der String, nur eben ständig mit einem "#0":
h#0t#0t#0p#0:#0/#0/#0w#0w#0w#0.#0g#0o#0o#0g#0l#0e#0.#0d#0e#0

Übrigens ist es für Delphi egal, ob es sich um einen WideString oder String handelt, der als Schlüssel steht. Bei beiden kommt es zu der komischen anzeige...

Was mache ich nun falsch?

MfG
xZise
Fabian
Eigentlich hat MS Windows ab Vista den Hang zur Selbstzerstörung abgewöhnt – mkinzler
  Mit Zitat antworten Zitat
Benutzerbild von negaH
negaH

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

Re: [DEC] WideString ver/entschlüsseln

  Alt 7. Jan 2008, 17:16
Hm so aus dem Stegreif weis ich auch nicht was falsch ist. Ein WideString ist aber ein Array of WideChar und WideChar ist ein 2 Bytes Datentyp. Bei Ansicode Zeichensatz wird nur 1 Byte davon real benutzt das andere muß immer 0 sein. Also sieht es eher so aus als ob die MessageBox() einen WideString als normalen String anzeigt oder aber als ob die VCL aus einem WideString einen Wide-WideString macht. Ich habe meine obigen Funktionen dahingehend getestet das ich das WideString Resultat im Debugger View im Speicherauszug angezeigt habe. Dann wirst du sehen das das Resultat ein echter WideString ist, also 2. Bytes wobei das 2. Byte pro Zeichen immer 0 ist. Es drängt sich also der Verdacht bei mir auf das irgendwas nach der Ver/Entschlüsselung, also in der Anzeigeroutine, falsch sein muß. Nur kann ich eben in deinem Source bisher keinen Fehler sehen. Kurz gesagt: ich denke das meine Funktionen alles richtig machen und der "Fehler" ausserhalb zu suchen ist. Leider habe ich bisher nur sehr wenig mit WideString gearbeitet und somit wenig Erfahrungen mit deren Eigenheiten.

Das Passwort sollte bei einer WideString Version natürlich auch WideString sein. Das macht zwar in unseren Regionen keinen wirklichen Sinn aber bei zb. Russischen oder Chinesischen Zeichensätzen ist es sehr wichtig. Denn jedes Bit an Information innerhalb des Passwortes bedeutet Sicherheit. Würde man ein WideString Passwort direkt in Cipher.Init() benutzen in dem jedes 2. Byte #0 ist so würde das die Sicherheit wieder reduzieren. Da wir aber mit einem Salt und einer KDF quasi die binären Daten des Passwortes in einen binären kompatiblen LongString als SessionKey umwandeln, entsteht dieses Sicherheitsrisiko nicht. Die KDF arbeitet quasi so ähnlich wie eine Komprimierungsfunktion aus Sicht der verwertbaren Entropie innerhalb der Passwortdaten.

Gruß Hagen

Achso: ein TypCast mit PChar() oder PWideChar() wandelt einen Delphi Datentyp, der intern eine separates Feld zu Längenangabe des Strings benutzt, in einen C typischen Nullterminierten String um. Sollte im Delphi Datentyp also ein #0-Teriminator mittten im String vorkommen, was durchaus ohne Probleme mit Delphis Datentypen möglich ist, dann wird durch diesen "Typcast" bzw. der später benutzten API Funktion der Strng quasi virtuell "abgeschnitten". Die API Funktion, zb. eine MessageBox() und damit die GDI Funktion DrawText() schneitet dann in der Anzeige diese String ab. Auch alle PChar/PWideChar Kopieroperatione wie StrLen(), StrCopy() usw. arbeiten mit dem #0-Terminator und schneiden die Delphi Datentypen ab. Normalwerweise kommen in einem String/LongString/WideString im Delphi ja keine #0-Terminatoren mitten im String vor. Aber im Falle vom DEC habe ich quasi den LongString als neuen Datentyp Binary mißbraucht um auch binäre Daten damit zu speichern. Das hat, wenn man nur mit Delphi Datentypen arbeitet enorme Vorteile. Man hat einen Stringkompatiblen binären Datentyp der 1 zu 1 zuweisungskompatibel ist, man hat Autallokation, Copy on Write Demand und eben Garbarge Collection über die Delphi interne Refernezzählung dieser Datentypen. Deshalb habe ich mich für LongStrings statt dynamsichem Array of Byte entschieden.
  Mit Zitat antworten Zitat
Benutzerbild von xZise
xZise

Registriert seit: 3. Mär 2006
Ort: Waldbronn
4.303 Beiträge
 
Delphi 2009 Professional
 
#17

Re: [DEC] WideString ver/entschlüsseln

  Alt 7. Jan 2008, 22:40
Naja Aber ich habe ja nie ein #0 im Widestring?!

MfG
xZise
Fabian
Eigentlich hat MS Windows ab Vista den Hang zur Selbstzerstörung abgewöhnt – mkinzler
  Mit Zitat antworten Zitat
Benutzerbild von negaH
negaH

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

Re: [DEC] WideString ver/entschlüsseln

  Alt 8. Jan 2008, 05:34
doch natürlich hast du das. Wenn du einen WideString als Speicherauszug betrachtest und der WideString enthält einen Ansi-compatiblen String dann wird jedes 2. Byte ein #0 sein. Also exakt so wie das was deine MessageBoxW() anzeigt. Nur das eben die MessageBoxW() eine WideString MessageBoxA() Variante ist und das ohne diese #0 Zeichen darstellen muß !!

Gruß Hagen
  Mit Zitat antworten Zitat
Benutzerbild von xZise
xZise

Registriert seit: 3. Mär 2006
Ort: Waldbronn
4.303 Beiträge
 
Delphi 2009 Professional
 
#19

Re: [DEC] WideString ver/entschlüsseln

  Alt 8. Jan 2008, 11:40
Aber wenn ich einen WideString im Debugger beobachte hat es keine #0 im String ?!
Oder ist dieser WideString dann kein Widestring?

MfG
xZise

[edit=1]Ich habe es geradeeben getestet:
TTntEdit (namens e) auf dem Formular, und dann folgende Methode:

Delphi-Quellcode:
procedure TForm1.FormClick(Sender: TObject);
var
  t : WideString;
begin
  t := e.Text;
  Showmessage(t);
  ShowMessage(t[2]);
end;
1. Showmessage gibt den WideString korrekt an.
2. Showmessage gibt das 2. Zeichen im WideString an (==> es ist kein #0 sondern das "dritte" Zeichen!)

Ein Beispiel:
WideString: "Hallo Welt"
t = "Hallo Welt" (auch im Debugger)
t[2] = "a" (und nicht wie zu erwarten #0)[/edit]

[edit=2]Ich habe mal ein Bild von einen Echten Widestring!
Keine #0 wie sie nach der entschlüsselung auftraten[/edit]
Miniaturansicht angehängter Grafiken
widestring_200.png  
Fabian
Eigentlich hat MS Windows ab Vista den Hang zur Selbstzerstörung abgewöhnt – mkinzler
  Mit Zitat antworten Zitat
Muetze1
(Gast)

n/a Beiträge
 
#20

Re: [DEC] WideString ver/entschlüsseln

  Alt 8. Jan 2008, 14:13
Zitat von xZise:
Aber wenn ich einen WideString im Debugger beobachte hat es keine #0 im String ?!
Weil der Debugger um den Typ weiß und ihn entsprechend darstellt. Darstellung ist ungleich Ablage. Im Speicher liegt er trotzdem (bei Ansi-Inhalt) mit jedem 2. Byte als #0 vor! Wenn du einen "echten" Widestring wie unten verwendest, dann ist wird das jeweils zweite Byte ordentlich genutzt.

Zitat von xZise:
[edit=1]Ich habe es geradeeben getestet:
TTntEdit (namens e) auf dem Formular, und dann folgende Methode:

Delphi-Quellcode:
procedure TForm1.FormClick(Sender: TObject);
var
  t : WideString;
begin
  t := e.Text;
  Showmessage(t);
  ShowMessage(t[2]);
end;
1. Showmessage gibt den WideString korrekt an.
2. Showmessage gibt das 2. Zeichen im WideString an (==> es ist kein #0 sondern das "dritte" Zeichen!)
WideString[] gibt dir auch einen WideChar zurück, und das ist ein Word. Wie willst du dort dann die Bytes betrachten?

Der indizierte Zeichenzugriff weiß doch um die Datenorganisation. Und wenn du WideString[] schreibst, dann gibst du das Zeichen an, auf das du zugreifen willst. Bei einem AnsiString[] ist es dann ein AnsiChar und der ist 8 Byte groß. Bei WideString[] ist es ein WideChar und der ist zwei Byte groß.

Delphi-Quellcode:
procedure TForm1.FormClick(Sender: TObject);
var
  t : WideString;
  lPtr: PByte;
begin
  t := e.Text;
  lPtr := @t[0];

  Showmessage(inttostr(lptr^) + ' ' + Chr(lPtr^));
  inc(lptr);
  Showmessage(inttostr(lptr^) + ' ' + Chr(lPtr^));
  inc(lptr);
  Showmessage(inttostr(lptr^) + ' ' + Chr(lPtr^));

  // alternativ:
  ShowMessage(format('high %d low %d', [Hi(t[2]), Lo(t[2])])); // wenn er WideChar nicht bei Hi() und Lo() akzeptiert, dann caste auf Word...
end;
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 2 von 3     12 3      


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 12:35 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz