Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Delphi <-> PHP Encryption / Decryption (https://www.delphipraxis.net/128314-delphi-php-encryption-decryption.html)

TDS 27. Jan 2009 19:22


Delphi <-> PHP Encryption / Decryption
 
Ich habe bis BDS 2006 DCPCrypt benutzt, leider in Delphi 2009 nicht mehr verwendbar da nicht unicode-fähig. Jetzt habe ich DEC 5.2 gefunden und es funzt in Delphi einwandfrei. Jedoch kann ich nicht mit PHP kommunizieren. Habe schon alles ausprobiert :-(

/*
* Verschlüsselung von Daten mit Passwort
*
* Verschlüsselt Daten mit RIJNDAEL (128bit).
* Gibt bei Erfolg verschlüsselten Text zurück.
*
* @param data Eingabetext
*
* @return verschlüsselter Text
*/
function encrypt($data, $key)
{
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_ECB); //get vector size on ECB mode
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND); //Creating the vector
$cryptedpass = mcrypt_encrypt (MCRYPT_RIJNDAEL_128, $key, $data, MCRYPT_MODE_ECB, $iv); //Encrypting using MCRYPT_RIJNDAEL_256 algorithm
return $cryptedpass;
/*
$str = mcrypt_cbc(MCRYPT_RIJNDAEL_128,$key,$data,MCRYPT_E NCRYPT,$iv);
return $str;
*/
}

/*
* Entschlüsselung von Daten mit Passwort
*
* Entschlüsselt Daten mit RIJNDAEL (128bit).
* Gibt bei Erfolg entschlüsselten Text zurück.
*
* @param data Eingabetext
*
* @return entschlüsselter Text
*/
function decrypt($data, $key)
{
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_ECB);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
$decryptedpass = mcrypt_decrypt (MCRYPT_RIJNDAEL_128, $key, $data, MCRYPT_MODE_ECB, $iv); //Decrypting...
return rtrim($decryptedpass);
/*
$str = mcrypt_cbc(MCRYPT_RIJNDAEL_128,$key,$data,MCRYPT_D ECRYPT,$iv);

// bis zum ersten 0-Byte
$len = strlen($str);
for ($i=0; $i<$len; $i++)
{
if (ord($str[$i]) == 0)
{
$str = substr($str, 0, $i);
break;
}
}
return $str;
*/
}
Delphi-Quellcode:
var
  ACipherClass: TDECCipherClass = TCipher_Rijndael;
  ACipherMode: TCipherMode = cmECBx;
  AHashClass: TDECHashClass = THash_MD5;
  ATextFormat: TDECFormatClass = TFormat_MIME64;
  AKDFIndex: LongWord = 1;

function Encrypt(const AText: String; const APassword: String): String; overload;
var
  ASalt: Binary;
  AData: Binary;
  APass: Binary;
begin
  MainForm.WriteLog('encrypt(): T=' + aText + ' P=' + APassword);
  with ValidCipher(ACipherClass).Create, Context do
  try
    ASalt := RandomBinary(16);
    APass := ValidHash(AHashClass).KDFx(APassword[1], Length(APassword) * SizeOf(APassword[1]), ASalt[1], Length(ASalt), KeySize, TFormat_Copy, AKDFIndex);
    Mode := ACipherMode;
    SetLength(AData, Length(AText) * SizeOf(AText[1]));
    Encode(AText[1], AData[1], Length(AData));
    Result := ValidFormat(ATextFormat).Encode(ASalt + AData + CalcMAC);
  finally
    Free;
    ProtectBinary(ASalt);
    ProtectBinary(AData);
    ProtectBinary(APass);
  end;
  MainForm.WriteLog('encrypt(): R=' + Result);
end;

function Encrypt(const AText: WideString; const APassword: WideString): WideString; overload;
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) * SizeOf(APassword[1]), ASalt[1], Length(ASalt), KeySize, TFormat_Copy, AKDFIndex);
    Mode := ACipherMode;
    Init(APass);
    SetLength(AData, Length(AText) * SizeOf(AText[1]));
    Encode(AText[1], AData[1], Length(AData));
    Result := ValidFormat(ATextFormat).Encode(ASalt + AData + CalcMAC);
  finally
    Free;
    ProtectBinary(ASalt);
    ProtectBinary(AData);
    ProtectBinary(APass);
  end;
  MainForm.WriteLog('encrypt(): ' + Result);
end;

function Decrypt(const AText: String; const APassword: String): String; overload;
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) * SizeOf(APassword[1]), ASalt[1], Length(ASalt), KeySize, TFormat_Copy, AKDFIndex);
    Mode := ACipherMode;
    Init(APass);
    SetLength(Result, ALen div SizeOf(AText[1]));
    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;

function Decrypt(const AText: WideString; const APassword: WideString): WideString; overload;
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) * SizeOf(APassword[1]), ASalt[1], Length(ASalt), KeySize, TFormat_Copy, AKDFIndex);
    Mode := ACipherMode;
    Init(APass);
    SetLength(Result, ALen div SizeOf(AText[1]));
    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;
Wer kann mir damit helfen?

TDS 27. Jan 2009 19:27

Re: Delphi <-> PHP Encryption / Decryption
 
Hier nochmal der PHP-Code zum testen:

// User entschlüsseln
$u1 = base64_encode(encrypt('abc', $global_crypt));
echo 'u1: '.$u1."\n";
$p1 = base64_encode(encrypt('xyz', $u1));
echo 'p1: '.$p1."\n";
$p1 = base64_encode(base64_encode(encrypt($p1, $global_crypt)));
echo 'p1: '.$p1."\n\n";

// Passwort entschlüsseln
echo 'p2: '.$p1."\n";
$p2 = decrypt(base64_decode(base64_decode($p1)), $global_crypt);
echo 'p2: '.$p2."\n";
$p2 = decrypt(base64_decode($p2), $u1);
echo 'p2: '.$p2."\n";
$u2 = decrypt(base64_decode($u1), $global_crypt);
echo 'u2: '.$u2."\n\n";

So, und hier teste ich mit der Übergabe von Delphi (DEC):

$user = '6l7GU7LYt04pVHc/00d7JjB/1bjCRn5n18SPwc/AK77qEUtTAEU=';
$c_user = decrypt(base64_decode($user), $global_crypt);
echo 'u1: '.$c_user."\n\n";

Assertor 27. Jan 2009 21:45

Re: Delphi <-> PHP Encryption / Decryption
 
Hi TDS,

erstmal ein herzliches Willkommen in der DP von mir!

Ich habe leider im Moment vor lauter Arbeit nicht viel Zeit, deswegen kann ich mich (noch) nicht genau mit dem Problem befassen bzw. habe den Code nur kurz überflogen. :oops:

Ein vielleicht hilfreicher Link zu einem ähnlichen Problem für die DEC 5.1:
http://www.delphipraxis.net/internal...hlight=php+dec

Vor allen Dingen die letzten Einträge dazu sind interessant.

Bist Du denn sicher, daß Du in beiden Sprachen den gleichen Initialisierungsvektor verwendest?

Gruß Assertor

himitsu 27. Jan 2009 22:35

Re: Delphi <-> PHP Encryption / Decryption
 
OK, D2009 ist zwar Unicode, aber sicher daß du deswegen gleich auf Unicode umstellen mußt/kannst?
> AnsiString

außerdem sind inhaltsmäßig String und WideString in D2009 auch das Selbe. (wenn ich mir das Ganze überladen da oben so anseh)

PS: für C gibt es das [c]-Tag und für PHP kannst du [code] verwenden (siehe Quellcodes im Beitragseditor)

TDS 28. Jan 2009 12:12

Re: Delphi <-> PHP Encryption / Decryption
 
Ich hatte erst einen IV für CBC mit "abcdefghijklmopq" (16 Zeichen). Da ging es ja auch. Nur nach Umstieg auf RAD 2009 geht da nichts mehr...
Wenn ich das richtig sehe, kann ich also von String auf AnsiString wechseln bei meinen Encrypt/Decrypt Version für DCPCrypt?
Oder kann ich gleich DEC 5.2 verwenden welches bereits lauffähig ist. Problem ist dort das CBC mit einen Random-IV initialisiert wird und dann noch via Hash verschlüsselt wird.

Ich benötige entweder CBC mit definierten IV ohen Hash oder EBC ohne IV und ohne Hash.

Bernhard Geyer 28. Jan 2009 12:21

Re: Delphi <-> PHP Encryption / Decryption
 
Zitat:

Zitat von TDS
Ich hatte erst einen IV für CBC mit "abcdefghijklmopq" (16 Zeichen). Da ging es ja auch. Nur nach Umstieg auf RAD 2009 geht da nichts mehr...

Wenn du es als String verwendest dann sind es jetzt 32 Bytes und nicht mehr 16 Bytes!

Assertor 30. Jan 2009 21:07

Re: Delphi <-> PHP Encryption / Decryption
 
Hi,

nochmal als kleine Hilfe:

http://www.delphipraxis.net/internal...hlight=dec+php
http://www.delphipraxis.net/internal...hlight=dec+php
http://www.delphipraxis.net/internal...hlight=dec+php
http://www.delphipraxis.net/internal...hlight=dec+php

Diese Threads behandeln alle im weitesten Sinne das Thema PHP <> Delphi Verschlüsselung.

Grundsätzlich sind folgende Fallstricke zu beachten:
- Welcher Hash und Cipher wird verwendet? (hier bereits bekannt)
- Welcher Initialisierungsvektor wird genutzt?
- Wird ein Salt verwendet?
- Ist ein Padding nötig und welches wird verwendet?
- Welches Format haben die Eingabe- und Ausgabedaten

Ich sehe in Deinem PHP code keinerlei Salt. Also muß der beim DEC auch raus, sonst kann das nicht gehen. Dann solltest Du entsprechend der anderen Threads den IV für PHP und Delphi festlegen, damit hier eine gleiche Basis vorliegt.

Die Formatierung in Base64/Mime64 ist ja auch bereits gelöst.

Der letzte Fallstrick ist Unicode. Hier kommt es auch auf den Webserver und dessen Einstellungen an. Du könntest von UTF8 kodierten Daten ausgehen und dann in Delphi 2009 mit UTF8Strings respektive AnsiStrings arbeiten und die Konversion manuell sicherstellen.

Damit sollten sich "beide Welten" problemlos verbinden lassen - auch wenn mit etwas Aufwand.

Darf ich fragen, wofür dieser Code verwendet werden soll? Wir hatten hier oft genug irgendwelche Windows-Passwort-Entschlüsselungsversuche und irgendwelche Download-Containerformate. Diesem will ich nicht Vorschub leisten, daher wäre ein konkreter Hintergrund etwas mehr Antrieb für die Mühe.

Gruß Assertor


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