Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   RIJNDAEL_256 Entschlüsseln mit DEC 5.2 (https://www.delphipraxis.net/168118-rijndael_256-entschluesseln-mit-dec-5-2-a.html)

DataCool 6. Mai 2012 01:29

RIJNDAEL_256 Entschlüsseln mit DEC 5.2
 
Hallo zusammen,

ich versuche gerade die verschlüsselte Rückgabe eines PHP-Scripts zu entschlüsseln.
Code:
function fnEncrypt($sValue, $sSecretKey)
{
    return trim(base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $sSecretKey, $sValue, MCRYPT_MODE_ECB, mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB), MCRYPT_RAND))));
}

function fnDecrypt($sValue, $sSecretKey)
{
    return trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $sSecretKey, base64_decode($sValue), MCRYPT_MODE_ECB, mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB), MCRYPT_RAND)));
}
Bisher hatte ich die DEC library, deshalb habe ich versucht mich einfach
an das mitgelieferte Bsp. zu halten.
Delphi-Quellcode:
var
  ACipherClass: TDECCipherClass = TCipher_Rijndael;
  ACipherMode: TCipherMode = cmECBx;           // <--- umgestellt passend zum PHP-Script
  AHashClass: TDECHashClass = THash_Whirlpool;
  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
  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;
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;
Wird der obere Code aufgerufen steigt diese in den DEC Lib hier aus:
Delphi-Quellcode:
function TDECCipher.CalcMAC(Format: TDECFormatClass): Binary;
begin
  Done;
  if FMode in [cmECBx] then raise EDECException.Create(sInvalidMACMode)
    else Result := ValidFormat(Format).Encode(FBuffer^, FBufferSize);
end;
Warum die Exception ausgelöst wird ist mir klar,
aber ist es richtig das "ECB" hier gar nicht unterstützt wird ?

Greetz Data

cookie22 6. Mai 2012 06:36

AW: RIJNDAEL_256 Entschlüsseln mit DEC 5.2
 
Ist möglich, dass ich hier jetzt totalen Mist schreibe, wenn es so ist, bitte drauf hinweisen.

Die Schlüsselerzeugung bzw. die Verschlüsselung sieht mir völlig unterschiedlich aus.

In der PHP Variante gibt es kein Gegenstück zur Key Derivation Function (KDFx). Dazu kommt noch, dass KDFx eine Dec-Eigene Key Derivation Function ist. Die PHP Funktion errechnet einen zufälligen IV, deine Delphi Version tut dies nicht. Außerdem sehe ich in der PHP Version nicht, dass dort ein MAC irgendwo geschrieben wird. Als AHashClass ist THash_Whirlpool deklariert, bist du sicher, dass die PHP Funktion auch mit Whirlpool arbeitet? Außerdem musst du überprüfen, wo die Informationen (Salt, IV, Mac, möglicherweise Informationen zum Passwort (Hash oder ein Teil davon) ) in der verschlüsselten Datei gespeichert werden.

Aus diesen Gründen kann das gar nicht klappen.

Delphi-Quellcode:
function TDECCipher.CalcMAC(Format: TDECFormatClass): Binary;
begin
  Done;
  if FMode in [cmECBx] then raise EDECException.Create(sInvalidMACMode)
    else Result := ValidFormat(Format).Encode(FBuffer^, FBufferSize);
end;
Wie du hier ja schon gesehen hast, kann das im ECB Mode gar nicht funktionieren. Muss es aber auch nicht, denn in deiner PHP Funtion wird ja auch gar kein MAC Wert errechnet.

Edit: Der ECB Modus ist nicht sonderlich sicher, deshalb sollte man lieber einen verketteten Modus wie CBC benutzen. ECB Mode Wiki

DataCool 6. Mai 2012 10:37

AW: RIJNDAEL_256 Entschlüsseln mit DEC 5.2
 
@cookie22:
Danke erstmal für Deine Antwort, wie ich schon sagte das ist das erste Mal das ich die DEC Lib verwende.
Somit habe ich das Example verwendet und den Mode auf ECB angepasst, weil ich das dem PHP Auszug entnehmen konnte.

Zitat:

Als AHashClass ist THash_Whirlpool deklariert, bist du sicher, dass die PHP Funktion auch mit Whirlpool arbeitet? Außerdem musst du überprüfen, wo die Informationen (Salt, IV, Mac, möglicherweise Informationen zum Passwort (Hash oder ein Teil davon) ) in der verschlüsselten Datei gespeichert werden.
Keine Ahnung welche HashClass im PHP-Script verwendet wird, bis jetzt habe ich nur den oberen Auszug gesehen.
Das im PHP-Script ECB verwendet wird ist doch richtig, Oder ? (MCRYPT_MODE_ECB)
Deshalb muss ich ja den ECB Modus verwenden, oder sehe ich das falsch.

Mein Ziel ist es ganz einfach den Output des Scripts zu entschlüsseln, muss auch nicht zwingend mit DEC sein.
Wie kann ich am besten vorgehen ?

Greetz Data

cookie22 6. Mai 2012 10:47

AW: RIJNDAEL_256 Entschlüsseln mit DEC 5.2
 
Wie gesagt, so einfach ist das ganze nicht.

Das mit dem ECB Mode ist schon richtig.

Du musst erst mal herausfinden wie $sSecretKey in PHP erzeugt wird, dann das ganze auf Delphi übertragen. Dann musst du den IV (Initialisierungsvektor) auslesen und diesen beim entschlüsseln verwenden. Und letzt endlich nicht die Base 64 Codierung vergessen.

Mehr kann ich dir da auch nicht sagen, weil ich in PHP nicht gereade firm bin.

DataCool 6. Mai 2012 10:59

AW: RIJNDAEL_256 Entschlüsseln mit DEC 5.2
 
@Cookie:
Den SecretKey weiß ich, den übergebe ich mit an das Script.
Naja, werde mich wohl in die ganze Thematik einlesen müssen.

Greetz Data


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