Delphi program using DCPcrypt not decrypted from PHP after upgrading to XE2

I have an application developed in Delphi 2007 in which the value is encrypted by PHP and decrypted in the application. The encryption algorithm is RIJNDAEL 128. When I moved XE2 and installed the latest version of DCPcrypt, the application starts, but can no longer decrypt the encrypted string from PHP. The result looks like Chinese characters, so I wonder if I need to modify my processing of the encryption key, vector or encrypted string to take into account the fact that XE2 uses Unicode characters.

The PHP font is executed as follows: (Mcrypt_cbc (MCRYPT_RIJNDAEL_128, $ key, $ date_str, mcrypt_encrypt, $ IV))

And two relevant Delphi functions:

function PadWithZeros(const str : string; size : integer) : string; var origsize, i : integer; begin Result := str; origsize := Length(Result); if ((origsize mod size) <> 0) or (origsize = 0) then begin SetLength(Result,((origsize div size)+1)*size); for i := origsize+1 to Length(Result) do Result[i] := #0; end; end; procedure TfrmMain.btnDecryptClick(Sender: TObject); var Cipher : TDCP_rijndael; Data, Key, IV : string; begin // Pad Key and IV with zeros as appropriate Key := PadWithZeros(boxKey.Text,KeySize); IV := PadWithZeros(boxIV.Text,BlockSize); // Decode the Base64 encoded string Data := Base64DecodeStr(boxCipherTextIn.Text); // Create the cipher and initialise according to the key length Cipher := TDCP_rijndael.Create(Self); if Length(boxKey.Text) <= 16 then Cipher.Init(Key[1],128,@IV[1]) else if Length(boxKey.Text) <= 24 then Cipher.Init(Key[1],192,@IV[1]) else Cipher.Init(Key[1],256,@IV[1]); // Decrypt the data Cipher.DecryptCBC(Data[1],Data[1],Length(Data)); // Free the cipher and clear sensitive information Cipher.Free; FillChar(Key[1],Length(Key),0); // Display the result boxPlainTextOut.Text := Data; end; 
+4
source share
2 answers

The problem is with character encoding, but not that DCPCrypt is unable to handle UTF-16.

PHP strings are UTF-8. This way you pass the password ("key") from PHP to Dephi as a base64 encoded string. In Bizarrely, you store the decoded key in a UTF-16LE string. More appropriate would be rawbytestring or TBytes or TMemoryStream. The binary layout of the key payload now differs from that it will be on the encoding side because it is printed as UTF16-LE (in incorrect Delphi terminology, the β€œUnicode string” is Microsoft and Embarcadero malapropism).

Also this line of code is incorrect in the 'unicode' (sic) compiler for obvious reasons ...

 FillChar(Key[1],Length(Key),0); 

Side note

I am the author of TurboPower LockBox 3, and the number one problem I get in the forums is due to the confusion between the lines ansistrings, utf-8 and utf-16le. Many people think that the password β€œabc”, as PHP understands, is the same password as β€œabc” in Delphi 2010. Which cryptographic libraries are used from password strings is a binary payload obtained by encoding a string, not its semantic meaning as a string.

+9
source

The application now compiles correctly in XE2 and can decrypt records from a version compiled with Delphi 2007. Thank you all for your comments. Different points of view help to understand when variables should be defined as ANSI strings.

If someone else is trying a similar update and needs to decrypt the encryption text generated in PHP, my decryption function and the supporting padWithZeros () function come from the DCPcrypt website, so I post my modified code here. I also did not have to install the DCPcrypt update for XE2 7/21/2012, available at the following address: http://www.pepak.net/files/tools/dcpcrypt.zip .

 function TForm1.AESDecrypt(const DecKeyStr: AnsiString; const DecIVStr: AnsiString; const CypherTextIn: AnsiString): String; var Cipher : TDCP_rijndael; Data, Key, IV : AnsiString; begin // Pad Key and IV with zeros as appropriate Key := PadWithZeros(DecKeyStr,KeySize); IV := PadWithZeros(DecIVStr,BlockSize); // Decode the Base64 encoded string Data := Base64DecodeStr(CypherTextIn); // Create the cipher and initialise according to the key length Cipher := TDCP_rijndael.Create(nil); if Length(DecKeyStr) <= 16 then Cipher.Init(Key[1],128,@IV[1]) else if Length(DecKeyStr) <= 24 then Cipher.Init(Key[1],192,@IV[1]) else Cipher.Init(Key[1],256,@IV[1]); // Decrypt the data Cipher.DecryptCBC(Data[1],Data[1],Length(Data)); // Free the cipher and clear sensitive information Cipher.Free; FillChar(Key[1],Length(Key),0); // Display the result Result := String(Data); (* *) end; function TForm1.PadWithZeros(const str:AnsiString; size:integer):AnsiString; var origsize, i : integer; begin Result := str; origsize := Length(Result); if ((origsize mod size) <> 0) or (origsize = 0) then begin SetLength(Result,((origsize div size)+1)*size); for i := origsize+1 to Length(Result) do Result[i] := #0; end; end; 
+3
source

All Articles