Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi [DEC] WideString ver/entschlüsseln (https://www.delphipraxis.net/105894-%5Bdec%5D-widestring-ver-entschluesseln.html)

xZise 1. Jan 2008 20:30


[DEC] WideString ver/entschlüsseln
 
Hallo DP,
wie kann ich mit DEC WideStrings verschlüsseln und dann entschlüsseln?

Standard ist ja folgendes:

Delphi-Quellcode:
function Encode(const Key: String; const Text: String): String;
var
  Salt: Binary;
begin
  with TCipher_Rijndael.Create do
  try
    Mode := cmCBCx;
    Salt := RandomBinary(16);
    Init(THash_SHA1.KDFx(Key, Salt, Context.KeySize));
    Result := TFormat_MIME64.Encode(Salt + EncodeBinary(Text));
  finally
    Free;
  end;
end;
Und wie kann ich diesen kodierten WideString dann speichern?
Am besten dann in ein Byte Array :)

MfG
xZise

mkinzler 1. Jan 2008 20:44

Re: [DEC] WideString ver/entschlüsseln
 
Versuch es doch mit der Funktion. Sollte ja so gehen, da in einem Unicodestring eine 2 in mehreren Zeichen abgebildet wird.

xZise 1. Jan 2008 21:32

Re: [DEC] WideString ver/entschlüsseln
 
Also so funktioniert es leider nicht:
Delphi-Quellcode:
function Encode(const Key: String; const Text: String): String;
var
  Salt: Binary;
begin
  with TCipher_Rijndael.Create do
  try
    Mode := cmCBCx;
    Salt := RandomBinary(16);
    Init(THash_SHA1.KDFx(Key, Salt, Context.KeySize));
    Result := TFormat_MIME64.Encode(Salt + EncodeBinary(Text));
  finally
    Free;
  end;
end;

function Decode(const Key: String; const Text: String): String;
var
  Data: Binary;
begin
  with TCipher_Rijndael.Create do
  try
    Mode := cmCBCx;
    Data := TFormat_MIME64.Decode(Text);
    Init(THash_SHA1.KDFx(Key, Copy(Data, 1, 16), Context.KeySize));
    Result := DecodeBinary(Copy(Data, 16, MaxInt));
  finally
    Free;
    ProtectBinary(Data);
  end;
end;
Wenn ich nun ein Passwort nehme und einen Text (WideString) bekomme ich nur die 4 letzten Zeichen wieder zurück.

Delphi-Quellcode:
str := Encode(frmPassword.mePasswd.Text, App.GetText);
ShowMessage(Decode(frmPassword.mePasswd.Text, str));
MfG
xZise

Luckie 1. Jan 2008 21:48

Re: [DEC] WideString ver/entschlüsseln
 
Du solltest hagen mal fragen, ob es die entsprechenden Funktionen auch für Unicode bzw. WideStrings gibt.

himitsu 3. Jan 2008 00:19

Re: [DEC] WideString ver/entschlüsseln
 
Ansonsten sollte es doch bestimmt eine Version für binäre Daten (statt der Strings) geben, welche du hierfür verwenden könntest.

Muetze1 3. Jan 2008 14:26

Re: [DEC] WideString ver/entschlüsseln
 
Zitat:

Zitat von himitsu
Ansonsten sollte es doch bestimmt eine Version für binäre Daten (statt der Strings) geben, welche du hierfür verwenden könntest.

Da die BASE64 Kodierung in lesbaren Zeichen zurück gibt, muss es schon ein ordentlich gesetzter WideString sein. Somit muss die Routine dem WideString Rechnung tragen und zwei folgende Bytes als Einheit sehen und entsprechend interpretieren. Wenn du dies einfach nur binär betrachtest, dann sollte kein Empfänger dies als String dekodieren können.

xZise 3. Jan 2008 21:21

Re: [DEC] WideString ver/entschlüsseln
 
Zitat:

Zitat von Muetze1
Zitat:

Zitat von himitsu
Ansonsten sollte es doch bestimmt eine Version für binäre Daten (statt der Strings) geben, welche du hierfür verwenden könntest.

Da die BASE64 Kodierung in lesbaren Zeichen zurück gibt, muss es schon ein ordentlich gesetzter WideString sein. Somit muss die Routine dem WideString Rechnung tragen und zwei folgende Bytes als Einheit sehen und entsprechend interpretieren. Wenn du dies einfach nur binär betrachtest, dann sollte kein Empfänger dies als String dekodieren können.

Also es kann auch binär kodiert sein ;)
BASE64 sagte mir nichts in dem Bezug.

xZise 6. Jan 2008 22:26

Re: [DEC] WideString ver/entschlüsseln
 
Ehm sry wenn ich pushe, aber ich bin etwas verwirrt:
Warum kann ich den ein String nicht binär ver- und wieder entschlüsseln?
Ich mein ein WideString hat eben ein paar "00" zwischen den Zeichen (wenn keine Sonderzeichen verwendet werden).

Und so richtig hat mir das auch nicht geholfen :)

MfG
xZise

Muetze1 6. Jan 2008 23:13

Re: [DEC] WideString ver/entschlüsseln
 
Wenn du es selbst auch wieder decodierst und es nicht irgendwem anders zur Decodierung weitergibst, kannst du es so machen. Eigentlich gibs dann kein Problem - von daher: was ist denn nun das Problem?

Die Verschlüsselung hat doch bestimmt eine Funktion die Entweder ein Const Parameter hat (ohne Typ) oder einen Pointer annimmt. Beim ersten gibst du einfach den WideString[0] an, beim zweiten PWideChar(WideString). Bei beiden vorher testen ob der String auch Zeichen enthält.

xZise 7. Jan 2008 00:34

Re: [DEC] WideString ver/entschlüsseln
 
Hi,
Ich verstehe gerade nicht, warum ich dort die Parameter ändern muss?

Ich habe eben das Problem, ein WideString zu haben, den ich verschlüsseln und entschlüsseln muss.
Nun wollte ich dafür das DEC verwenden, da es dafür ja perfekt ist.
Und aufgrund der hohen Sicherheit von AES bzw. Rijndael benutze ich diesen.

Meine konkrete Frage und das Problem ist jetzt: Kann man mithilfe von DEC ein WideString verschlüsseln? Was herauskommt (String, WideString, ByteArray) ist egal,
hauptsache das entschlüsseln funktioniert dann.

Zur Zeit funktioniert noch nichtmal folgendes:
Delphi-Quellcode:
function Encode(const Key: String; const Text: String) : String;
var
  Salt: Binary;
  cipher : TCipher_Rijndael;
begin
  cipher := TCipher_Rijndael.Create;
  try
    cipher.Mode := cmCBCx;
    Salt := RandomBinary(16);
    cipher.Init(THash_SHA1.KDFx(Key, Salt, cipher.Context.KeySize));
    Result := TFormat_MIME64.Encode(Salt + cipher.EncodeBinary(Text));
  finally
    cipher.Free;
  end;
end;

function Decode(const Key: String; const Text: String) : String;
var
  Data: Binary;
  cipher : TCipher_Rijndael;
begin
  cipher := TCipher_Rijndael.Create;
  try
    cipher.Mode := cmCBCx;
    Data := TFormat_MIME64.Decode(Text);
    cipher.Init(THash_SHA1.KDFx(Key, Copy(Data, 1, 16), cipher.Context.KeySize));
    Result := cipher.DecodeBinary(Copy(Data, 16, MaxInt));
  finally
    cipher.Free;
    ProtectBinary(Data);
  end;
end;
Aufruf:
ShowMessage(Decode('HW', Encode('HW', 'Die Welt ist nicht genug')));
Ergebnis:
siVµ³äµsF}×—Néòht genug

MfG
xZise

Muetze1 7. Jan 2008 07:12

Re: [DEC] WideString ver/entschlüsseln
 
Ich weiß nicht wie der Typ Binary definiert ist, aber meine ganzen Erklärungen bezogen sich nur darauf, dass du bei folgendem Konstrukt
Delphi-Quellcode:
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.

negaH 7. Jan 2008 09:38

Re: [DEC] WideString ver/entschlüsseln
 
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ß.

negaH 7. Jan 2008 09:57

Re: [DEC] WideString ver/entschlüsseln
 
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

negaH 7. Jan 2008 10:05

Re: [DEC] WideString ver/entschlüsseln
 
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

xZise 7. Jan 2008 13:25

Re: [DEC] WideString ver/entschlüsseln
 
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

negaH 7. Jan 2008 16:16

Re: [DEC] WideString ver/entschlüsseln
 
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.

xZise 7. Jan 2008 21:40

Re: [DEC] WideString ver/entschlüsseln
 
Naja ;) Aber ich habe ja nie ein #0 im Widestring?!

MfG
xZise

negaH 8. Jan 2008 04:34

Re: [DEC] WideString ver/entschlüsseln
 
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

xZise 8. Jan 2008 10:40

Re: [DEC] WideString ver/entschlüsseln
 
Liste der Anhänge anzeigen (Anzahl: 1)
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]

Muetze1 8. Jan 2008 13:13

Re: [DEC] WideString ver/entschlüsseln
 
Zitat:

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:

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;

negaH 8. Jan 2008 16:47

Re: [DEC] WideString ver/entschlüsseln
 
Zitat:

Aber wenn ich einen WideString im Debugger beobachte hat es keine #0 im String ?!
Doch hat er, nur du betrachtest den WideString falsch. Oben schrieb ich explizit -> im Speicherauszug. Also im DebugView die Checkbox "Speicherauszug" anhacken, bitte ;)

Gruß hagen

xZise 8. Jan 2008 17:56

Re: [DEC] WideString ver/entschlüsseln
 
Hallo Mütze und Hagen,

ich glaube kaum, dass es tatsächlich am debugger liegt, dass er #0 einfügt.
Zitat:

Zitat von Muetze1
Zitat:

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.

Jap... Aber ich meine, warum sollte er mitten drinne die Anzeige verändern?
Es ist die gleiche Variable vom Typ "WideString", also sollte der Debugger eigentlich selbstständig erkennen, dass es aus Words bzw. WideChars besteht?
Ich meine wenn man sowas macht:
Delphi-Quellcode:
var
  myWideString : WideString;

myWideString := 'Ein WideString';
myWideString := TueDasUndDas(myWideString);
Warum sollte, wenn als Ergebnis von TueDasUndDas wieder ein WideString herauskommt, aufeinmal #0 mitten im String auftauchen?

Zitat:

Zitat von Muetze1
Zitat:

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;

Nagut, dieser "Beweis" ist nicht ganz aussagekräftig.


Zitat:

Zitat von negaH
Zitat:

Aber wenn ich einen WideString im Debugger beobachte hat es keine #0 im String ?!
Doch hat er, nur du betrachtest den WideString falsch.[...]

Genau das gleiche wie oben: Warum sollte der Debugger auf einmal die Anzeige umschalten?

Nagut, selbst wenn ihr darauf einen Grund habt:
Ich habe diesmal debuggt mit Speicherauszug, und das Ergebnis seht hier:

Vor der Entschlüsselung und Verschlüsselung:
Code:
$68 $00 $74 $00 $74 $00 $70 $00 $3A $00 $2F $00 $2F $00 $77 $00 $77 $00 $77 $00 $2E $00 $67 $00 $6F $00 $6F $00 $67 $00 $6C $00 $65 $00 $2E $00 $64 $00 $65 $00
Nach der Entschlüsslung und Verschlüsselung:
Code:
$68 $00 [b]$00 $00[/b] $74 $00 [b]$00 $00[/b] $74 $00 [b]$00 $00[/b] $70 $00 $00 $00 $3A $00 $00 $00 $2F $00 $00 $00 $2F $00 $00 $00 $77 $00 $00 $00 $77 $00 $00 $00 $77 $00 $00 $00 $2E $00 $00 $00 $67 $00 $00 $00 $6F $00 $00 $00 $6F $00 $00 $00 $67 $00 $00 $00 $6C $00 $00 $00 $65 $00 $00 $00 $2E $00 $00 $00 $64 $00 $00 $00 $65 $00 $00 $00
(http://www.google.de)

Was sehen wir: 3 Byte (also genau 2 Byte zu viel) Nullen ;)
Ich habe nur die ersten 3 falschen Zeichen markiert.

MfG
xZise

[edit=1]Ich habe mal die Antwort verbessert...[/edit]
[edit=2]Ich habe das Ergebnis des Debuggers vor und nach der "Tortur" ( ;) ) angegeben und mal ein bisschen gehighlightet[/edit]

DGL-luke 8. Jan 2008 18:35

Re: [DEC] WideString ver/entschlüsseln
 
Tja, mein Verdacht: Irgendjemand interpretiert den Widestring als Ansistring und wandelt in wieder in einen Widestring um.

xZise 8. Jan 2008 18:47

Re: [DEC] WideString ver/entschlüsseln
 
Naja, da kommt an sich nur das Verschlüsseln etc. in betracht:
Delphi-Quellcode:
decryptedText := <WideString>; // Eine speicherung in der Variable, damit der Debugger den Inhalt anzeigt
str := EncryptW(<WideString>, <Passwort (WideString)>); // Verschlüsselung (PW + Text sind jetzt Widestrings)
if DecryptW(str, <Passwort (WideString)>, decryptedText) then // Entschlüsslung mit dem Passwort der Zeile drüber, also identisch
begin
  fs.Write(Pointer(str)^, Length(str)); // Speicherung des Strings
end;
1. Abfrage in der ersten Zeile und die zweite Abfrage nachdem er die 3. Zeile durchlaufen ist.

MfG
xZise

[edit=1]Interessant ist, dass die Entschlüsselung als Result dennoch true zurückgibt, obwohl sie eigentlich false ergeben sollte (oder?)[/edit]

Muetze1 8. Jan 2008 20:09

Re: [DEC] WideString ver/entschlüsseln
 
Alles von mir - auf was du dich so schön beziehst - hatte ich auf folgende 0-Bytes bezogen:

Zitat:

Zitat von xZise
Vor der Entschlüsselung und Verschlüsselung:
Code:
$68 [b]$00[/b] $74 [b]$00[/b] $74 [b]$00[/b] $70 [b]$00[/b] $3A [b]$00[/b] $2F [b]$00[/b] $2F [b]$00[/b] $77 [b]$00[/b] $77 [b]$00[/b] $77 [b]$00[/b] $2E [b]$00[/b] $67 [b]$00[/b] $6F [b]$00[/b] $6F [b]$00[/b] $67 [b]$00[/b] $6C [b]$00[/b] $65 [b]$00[/b] $2E [b]$00[/b] $64 [b]$00[/b] $65 [b]$00[/b]

Und in Bezug darauf, dass der Debugger diesen (ordentlichen) WideString natürlich als WideString ausgibt und somit diese oben genannten 0-Bytes nicht ausgibt. Und da dein Beispiel, um die 0-Bytes zu beweisen, wegen den WideChar niemals ein solchen bringen sollte, habe ich den ganzen Lex dort oben geschrieben.

Das bei dir im Endeffekt aber $00 $00 zusätzlich pro Zeichen im String sind, war nicht Gegenstand meines Beitrags.

/EDIT: Wir reden vollkommen aneinander vorbei. Von daher: vergiß es. Diskussion (mit mir) beendet.

xZise 8. Jan 2008 20:24

Re: [DEC] WideString ver/entschlüsseln
 
Zitat:

Zitat von Muetze1
Alles von mir - auf was du dich so schön beziehst - hatte ich auf folgende 0-Bytes bezogen:[...]

Ich habe doch nie geleugnet, dass bei WideStrings die #0 jedes 2. Byte sind, was ich aber ständig versuche zu zeigen, ist dass am Ende, da zwei Bytes zu viel auftauchen.
Und ich verstehe nicht so richtig, was du mir damit zeigst?

Ich könnte die natürlich in einer Schleife entfernen, oder der Fehler wird direkt eingedämmt.

MfG
xZise

negaH 8. Jan 2008 21:06

Re: [DEC] WideString ver/entschlüsseln
 
Also doch ein Wide-WideString. Irgendeine Typumwandlung macht aus einem WideString einen doppelt-gemoppelten Wide-WideString. Schau mal ob du bei MessageBoxW(PWideChar(WideStrng),...) mit MessageBoxW(PWideChar(@WideString[1]), ...) oder MessageBoxW(Pointer(@WideString[1]),...) was erreichen kannst.


Gruß Hagen

xZise 8. Jan 2008 22:28

Re: [DEC] WideString ver/entschlüsseln
 
Hi Hagen,
weder noch erreichen, dass der WideString dabei bleibt.

MfG
xZise

negaH 9. Jan 2008 21:20

Re: [DEC] WideString ver/entschlüsseln
 
Ok, probier das nochmal aus.

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);
    SetLength(Result, ALen div 2);
    Decode(AData[1], Result[1], ALen);
    if ACheck <> CalcMAC then
      raise Exception.Create('Invalid data');
  finally
    Free;
    ProtectBinary(ASalt);
    ProtectBinary(AData);
    ProtectBinary(ACheck);
    ProtectBinary(APass);
  end;
end;
Gruß Hagen

xZise 9. Jan 2008 21:31

Re: [DEC] WideString ver/entschlüsseln
 
Hallo Hagen,
mit dieser Version funktioniert.
Nun habe ich die "Stringausgabe"-Variante benutzt.
Vielleicht funktionierte die nur nicht...

MfG
xZise


Alle Zeitangaben in WEZ +1. Es ist jetzt 23:15 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