1

I am trying to exchange encrypted messages between Delphi and PHP.

From the Delphi side I downloaded DCPcrypt v2 Beta 3 from here:

http://www.cityinthesky.co.uk/opensource/dcpcrypt/

For encrypting I use this function:

function TForm1.Encrypt3DES(psData, psKey: string): string;
var
  Cipher: TDCP_3des;
begin
  Cipher:= TDCP_3des.Create(nil);
  Cipher.InitStr(psKey,TDCP_sha256);
  result:=Cipher.EncryptString(psData);
  Cipher.Burn;
  Cipher.Free;
end;

And I am testing it like this:

ShowMessage(Encrypt3DES('test','SecretKeySecretKeySecret'));

The result that I get is Z74E0Q== and I can successfully decrypt it with another similar delphi function:

function TForm1.Decrypt3DES(psData, psKey: string): string;
var
  Cipher: TDCP_3des;
begin
  Cipher:= TDCP_3des.Create(nil);
  Cipher.InitStr(psKey, TDCP_sha256);         
  result:=Cipher.DecryptString(psData);
  Cipher.Burn;
  Cipher.Free;
end;

From PHP side I tried several function to encrypt the same string ('test') with the same key ('SecretKeySecretKeySecret') but the result is different from what I get in Delphi. Again I can successfully decrypt the messages in PHP with similar functions but I need to decrypt messages in Delphi.

This is what I do in PHP, I even tried to hash the key as I see Delphi function is using TDCP_sha256 but still results are diferent.

$key = "SecretKeySecretKeySecret";

echo base64_encode(mcrypt_encrypt(MCRYPT_3DES, $key, 'test', 'ecb')).'<BR><BR>';

echo openssl_encrypt('test', 'des-ede3', $key).'<BR><BR>';

$key = hash('sha256', $key);
echo openssl_encrypt('test', 'des-ede3', $key).'<BR><BR>';

This is the result:

Z05z5Bp4/vY=

L5qmk5nJOzs=

bm7yRdrMs5g=

What am I doing wrong? BTW I am using Delphi 7 and DCPcrypt is the only library for now that I managed to make it run.

Val Marinov
  • 2,705
  • 17
  • 22
Georgi Bonchev
  • 269
  • 4
  • 12
  • In Delphi 7 is used AnsiString(8-bit (ANSI) characters). What type of strig is used in PHP? If Unicode string is used, the result of encryption will be diferent. – Val Marinov Jul 05 '18 at 07:24
  • @ValMarinov that was a good suggestion but it seems this is not the case. I used UTF8String('test') in Delphi, it did not change the result. Then I used $text = iconv("UTF-8", "Windows-1252", "test") in PHP and again no change. I even converted the key in both Delphi and PHP but I aways get the same result. – Georgi Bonchev Jul 05 '18 at 07:51
  • Doesn't look like those functions would be expected to do the same thing. Why did you decide to code them that way, or have you just copied the code from some online sources without really understanding all the implications? – David Heffernan Jul 05 '18 at 07:55

2 Answers2

5

I think that this will help you. TDCP_3des is blockcipher and EncryptString method uses EncryptCFB8bit method (Encrypt size bytes of data using the CFB (8 bit) method of encryption).

Two things are important:

  • use the same initialisation vector
  • hash the key in PHP part.

Delphi part:

function TForm1.Encrypt3DES(psData, psKey: string): string;
var
   Cipher: TDCP_3des;
   i: integer;
begin
   Cipher := TDCP_3des.Create(nil);
   try
      Cipher.InitStr(psKey, TDCP_sha256);
      Cipher.SetIV('00000000');
      Result := Cipher.EncryptString(psData);
      Cipher.Burn;
   finally
      Cipher.Free;
   end{try};
end;

procedure TForm1.btnEncryptClick(Sender: TObject);
var
   input, key: string;
begin
   input := 'Some words in English';
   key   := 'SecretKeySecretKeySecret';
   ShowMessage(Encrypt3DES(input, key));
end;

PHP part:

<?
$key = "SecretKeySecretKeySecret";
$key = hash('sha256', $key, true);
$key = substr($key, 0, 24);
$iv = '00000000';

$message = 'Some words in English';
$result = mcrypt_encrypt(MCRYPT_3DES, $key, $message, MCRYPT_MODE_CFB, $iv);
$result = base64_encode($result);
echo 'Input text: '.$message.'</br>';
echo 'Encrypted text: '.$result.'</br>';
?>

Output:

Input:          Some words in English                           
Encrypted text: hTpdn+USolFTgv/4HnBEvo4scgmp
Input:          This will test Delphi7 and PHP encryption.
Encrypted text: gik2Iw/m2rtMA9gdKqvFqDg3kuUSb4rnAieyZ8unIvt510Rbt1jLPO+/      
Input:          I hope this will work.                          
Encrypted text: n/JxW12zORaI7TSCAF4/6cBxqC3mZg== 

Notes:

Tested with Delphi 7, DCPcrypt v2, PHP 5.2.10, mcrypt 2.5.7.

Zhorov
  • 28,486
  • 6
  • 27
  • 52
2

The length of your base64 ciphertext shows that DCPCrypt does not use ECB. With a minimal program I can reproduce your result and stepping through the code indeed shows that ECB is not used. The relevant parts are

function TDCP_blockcipher.EncryptString(const Str: string): string;
begin
  SetLength(Result,Length(Str));
  EncryptCFB8bit(Str[1],Result[1],Length(Str));
  Result:= Base64EncodeStr(Result);
end;

function TDCP_blockcipher.DecryptString(const Str: string): string;
begin
  Result:= Base64DecodeStr(Str);
  DecryptCFB8bit(Result[1],Result[1],Length(Result));
end;
gammatester
  • 1,131
  • 1
  • 8
  • 12
  • Thanks, I should have seen this. Unfortunatelly I don't see how to add iv vector in Delphi. In PHP it is a parameter. – Georgi Bonchev Jul 05 '18 at 09:07
  • @georgi-bonchev: ECB does not use an IV. But be aware of the different padding modes. (Anyway to set the IV use `TDCP_blockcipher64.SetIV(const Value);`) – gammatester Jul 05 '18 at 09:26