Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Ansistring zu Unicodestring (UTF16LE) (https://www.delphipraxis.net/158266-ansistring-zu-unicodestring-utf16le.html)

Garfield 10. Feb 2011 22:44

Ansistring zu Unicodestring (UTF16LE)
 
Bei der Anmeldung an der Fritzbox wird ein Response benötigt, für welchen die Challenge mit dem Password zu einem UTF16LE formatierten String und der daraus resultierende MD5Hash wiederum mit der Challenge verbunden wird:

Delphi-Quellcode:
aResponse := FSession.Challenge + '-' +  MD5Hash(AnsiToUtf16(Format('%s-%s', [FSession.Challenge, FPassword])));
Die Function
Delphi-Quellcode:
function AnsiToUtf16(const aStr: AnsiString): WideString;
var
  len : integer;
  codePage : Word;
begin
  codePage := CP_ACP;
  len := MultiByteToWideChar(codePage, MB_PRECOMPOSED, PChar(@aStr[1]), - 1, nil, 0);
  SetLength(Result, len - 1);
  if len > 1
  then MultiByteToWideChar(CodePage, MB_PRECOMPOSED, PChar(@aStr[1]), - 1, PWideChar(@Result[1]), len - 1);
end;
liefert wohl ein UTF16BE, aber kein UTF16LE. Der Versuch, jedes Char mit einem #0 zu ergänzen, hat nicht funktioniert.

Gibt es eine Lösung ohne auf ein neues Delphi updaten zu müssen?

himitsu 11. Feb 2011 01:18

AW: Ansistring zu Unicodestring (UTF16LE)
 
Entweder danach auch nochmal versuchen mit WideCharToMultiByte nun den Text nochmal nach CodePage 1201 (ich hoffe das stimmt) umwandeln

oder du drehst einfach alle Bytes/Chars manuell um.
Delphi-Quellcode:
for i := 1 to Length(S) do
  S[i] := Chr((Ord(S[i]) shl 8) or (Ord(S[i]) shr 8));
Auch wenn ich das jetzt eventuell wieder verwechsle,
(hab wohl eine Links-Rechs-Schwäche mit oder heißt das Groß-Klein? )
aber ist der UnicodeString/WideString nicht schon LittleEndian, also UTF16LE?

CP_UTF16 = 1200 (UTF16LE) und ich glaub die 1201 war UTF16BE

PS: AnsiString > WideString ... da wandelt Delphi das automatisch um.


Nur um es erwähnt zu haben, aber ab Delphi 2009 gibt es auch noch TUnicodeEncoding, TBigEndianUnicodeEncoding und kein explizites LittleEndian, da es das implizit schon gibt.

PS: Wie du das mit dem um eine #0 ergänzen gemeint hast, hab ich nicht richtig verstanden. (bzw, ich glaub ich weiß was du meinst, aber nicht das wie, so daß es dann komischer Weise nicht ging)

Garfield 11. Feb 2011 06:34

AW: Ansistring zu Unicodestring (UTF16LE)
 
Obwohl
Delphi-Quellcode:
function Chr ( IntValue : Integer ) : AnsiChar;
function Chr ( IntValue : Integer ) : WideChar;
sein soll, bekomme ich in Turbo Delphi bei
Delphi-Quellcode:
for i := 1 to Length(S) do
  S[i] := Chr((Ord(S[i]) shl 8) or (Ord(S[i]) shr 8));
die Meldung
Code:
[Pascal Fehler]E2010 Inkompatible Typen: 'WideChar' und 'Char'
Nachtrag: Mit WideChar anstelle Chr geht es. Aber das Passwort ist dann immernoch ungültig.
___

Die Codepage bezieht sich auf den Ausgangsstring und so bekomme ich bei 1200 und 1201 eine Länge von 0.
___

In der D2010-Komponente, welche ich zu Hilfe genommen habe, wird String verwendet und bei der Ermittlung des MD5 Hash wird in der unit DCPcrypt2 UpdateStr aufgerufen, welche so deklariert ist:
Delphi-Quellcode:
    procedure UpdateStr(const Str: AnsiString); {$IFDEF UNICODE}overload; {$ENDIF}
      { Update the hash buffer with the string }
{$IFDEF UNICODE}
    procedure UpdateStr(const Str: UnicodeString); overload;
      { Update the hash buffer with the string }
{$ENDIF}
Bedeutet dann wohl, dass Unicodestring UTF16LE sein müsste.
___

Zitat:

Zitat von himitsu (Beitrag 1080979)
PS: Wie du das mit dem um eine #0 ergänzen gemeint hast, hab ich nicht richtig verstanden. (bzw, ich glaub ich weiß was du meinst, aber nicht das wie, so daß es dann komischer Weise nicht ging)

So etwas:
Delphi-Quellcode:
Result := '';
for i := 1 to Length(aStr)
do Result := Result + aStr[i] + #0;
___

Nachtrag: Danach scheint ein Unicodesting tatsächlich LE zu sein.
___

Das ist die Beschreibung in der AVM Technical Note:
Zitat:

Ermittlung des Response-Wertes
Beim neuen Login-Verfahren wird also das Klartextpasswort
login:command/password=<klartextpassword>
ersetzt durch
login:command/response=<response>
Der Response-Wert wird wie folgt gebildet:
<response> = <challenge>-<md5>
Der Wert <challenge> kann aus der Datei login_sid.xml ausgelesen werden
und <md5> ist der MD5 (32 Hexzeichen mit Kleinbuchstaben) von
<challenge>-<klartextpassword>
Der MD5-Hash wird über die Bytefolge der UTF-16LE-Codierung dieses Strings gebildet (ohne BOM und
ohne abschließende 0-Bytes).
Aus Kompatibilitätsgründen muss für jedes Zeichen, dessen Unicode Codepoint > 255 ist, die Codierung
des "."-Zeichens benutzt werden (0x2e 0x00 in UTF-16LE). Dies betrit also alle Zeichen, die nicht in
ISO-8859-1 dargestellt werden können, z. B. das Euro-Zeichen.
Abschließend ein Beispiel mit deutschem Umlaut:
Die Challenge
<challenge> = "1234567z"
kombiniert mit dem Kennwort
<klartextpassword> = "äbc"
ergibt den Wert
<response> = "1234567z-9e224a41eeefa284df7bb0f26c2913e2"

Garfield 11. Feb 2011 07:10

AW: Ansistring zu Unicodestring (UTF16LE)
 
:oops: Habe jetzt mal das Beispiel aus der AVM Technical Note
Zitat:

Die Challenge
<challenge> = "1234567z"
kombiniert mit dem Kennwort
<klartextpassword> = "äbc"
ergibt den Wert
<response> = "1234567z-9e224a41eeefa284df7bb0f26c2913e2"
als Test verwendet und musste feststellen, dass der richtige MD5Hash herauskommt. Damit ist die Codierung nicht der Grund für das ungültige Passwort.

himitsu 11. Feb 2011 08:12

AW: Ansistring zu Unicodestring (UTF16LE)
 
Mist, stümmt, in Delphi 7 ist Chr ja noch ANSI. :oops: Chr=(WideChar und eventuell noch Ord=Word, damit es logischer zusammenpaßt)

Ja, die CodePages 1200 und 1201 sind nur vitruelle Codepages, und es gib einige Funktionen, welche damit nicht zurechtkommen ... war mir nur nicht mehr ganz sicher, ob WideCharToMultiByte damit zurecht kommt.


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