2

I am trying to encrypt / decrypt a string using Rijndael from php to Delphi and back.

If I decrypt a PHP string from Delphi ... works fine.

If I encrypt a string with Delphi the result string is ok but shorter

for test I used a string with 62 character. the encrypted string with delphi is long 4 char less of PHP

these the strings ... last characters:

PHP: GyLWj1anBJRmE8mBsaO5cvTrcbvvA==

Delphi: GyLWj1anBJRmE8mBsaO5cvTrcbv

thanks for any advices

I use this source code example:

PHP:

function encrypt ($key, $value)
{
  $padSize = 16 - (strlen ($value) % 16) ;
  $value = $value . str_repeat (chr ($padSize), $padSize) ;
  $output = mcrypt_encrypt (MCRYPT_RIJNDAEL_128, $key, $value, MCRYPT_MODE_CBC, 'xxxxxxx') ;
  return base64_encode ($output) ;
}

Delphi encrypt:

function EncryptData3(Data: string; AKey: AnsiString; AIv: AnsiString): string;
var
  cipher: TDCP_rijndael;
  key, iv, src, dest, b64: TBytes;
  index, slen, bsize, pad: integer;
begin
  //key := Base64DecodeBytes(TEncoding.UTF8.GetBytes(AKey));
  //iv := Base64DecodeBytes(TEncoding.UTF8.GetBytes(AIv));
  key := TEncoding.ASCII.GetBytes(AKey);
  iv := TEncoding.ASCII.GetBytes(AIv);

  src := TEncoding.ascii.GetBytes(Data);

  cipher := TDCP_rijndael.Create(nil);
  try
    cipher.CipherMode := cmCBC;
    // Add padding.
    // Resize the Value array to make it a multiple of the block length.
    // If it's already an exact multiple then add a full block of padding.
    slen := Length(src);
    bsize := (cipher.BlockSize div 8);
    pad := bsize - (slen mod bsize);
    Inc(slen, pad);
    SetLength(src, slen);

    for index := pad downto 1 do
    begin
      src[slen - index] := pad;
    end;

    SetLength(dest, slen);
    cipher.Init(key[0], 256, @iv[0]); // DCP uses key size in BITS not BYTES
    cipher.Encrypt(src[0], dest[0], slen);

    b64 := Base64EncodeBytes(dest);
    result := TEncoding.Default.GetString(b64);
  finally
    cipher.Free;
  end;
end;

Delphi decrypt ... not works:

function DecryptData3(Data: string; AKey: AnsiString; AIv: AnsiString): string;
var
  key, iv, src, dest: TBytes;
  cipher: TDCP_rijndael;
  slen, pad: integer;
begin
  //key := Base64DecodeBytes(TEncoding.UTF8.GetBytes(AKey));
  //iv := Base64DecodeBytes(TEncoding.UTF8.GetBytes(AIv));
  key := TEncoding.ASCII.GetBytes(AKey);
  iv := TEncoding.ASCII.GetBytes(AIv);

  src := Base64DecodeBytes(TEncoding.UTF8.GetBytes(Data));

  cipher := TDCP_rijndael.Create(nil);
  try
    cipher.CipherMode := cmCBC;
    slen := Length(src);
    SetLength(dest, slen);
    cipher.Init(key[0], 256, @iv[0]); // DCP uses key size in BITS not BYTES
    cipher.Decrypt(src[0], dest[0], slen);
    // Remove the padding. Get the numerical value of the last byte and remove
    // that number of bytes
    pad := dest[slen - 1];
    SetLength(dest, slen - pad);

    // Base64 encode it
    result := TEncoding.Default.GetString(dest);
  finally
    cipher.Free;
  end;
end;
acarlomagno
  • 79
  • 1
  • 2
  • 6
  • If want to read all questions/answers or blog articles in the whole WWW dealing with **this** you can spend some years on. Here on SO this question is asked nearly once a week just in the delphi corner. – Sir Rufo Feb 09 '15 at 15:54
  • I found the two answers to the problem ... but it does not solve anything. – acarlomagno Feb 09 '15 at 16:10
  • Ken, the linked answer does *not* have an accepted answer. – Leonardo Herrera Feb 09 '15 at 16:26
  • [Possible duplicates](https://stackoverflow.com/search?q=%5Bdelphi%5D+Rijndael+%5Bphp%5D+is%3Aquestion). – Free Consulting Feb 09 '15 at 17:42
  • Have a look [here](http://stackoverflow.com/a/24333787/1322642) . Maybe this answer can help you something. – moskito-x Feb 09 '15 at 18:04
  • I read this differently from those arguing for dupes. Asker has written good quality code that demonstrates a clear understanding of encryption. There just seems to be a minor bug seemingly relating to padding. Most of the questions we get in this area, an heaven knows we get a lot of them, contain dire code which are little more than "please write my code" requests. – David Heffernan Feb 09 '15 at 18:16
  • @acar Looks like a difference in padding handling. The == don't matter. They are just base64 artifacts. The difference is just two base64 chars. I suggest you compare the binary. – David Heffernan Feb 09 '15 at 18:18
  • 1
    To be clear then `vA==` represents a single byte. So there's a one byte difference between the two encrypted texts. You are clearly close. I'd try to find out what that one byte difference is. – David Heffernan Feb 09 '15 at 19:01
  • It has value `BC` in hex, but that doesn't say much (to me). – Maarten Bodewes Feb 09 '15 at 19:13
  • @acarlomagno : don't do a `return base64_encode ($output) ;` on both side. Compare instead the hex data. : php : `$hex2 = bin2hex($output); return strtoupper($hex2);` – moskito-x Feb 09 '15 at 20:50
  • Ken, it's true, but IMHO the answer not resolve the question ... then it not could be accepted – acarlomagno Feb 10 '15 at 15:12
  • @acarlomagno Accept or not is not really relevant. What matters is if the question is the same or not. The answers are largely irrelevant. What would be good would be if you could put some legwork in to debug this. How are you getting on? – David Heffernan Feb 10 '15 at 16:22
  • @moskito-x I have compared the HEX result .. are equal.. Seems that the problem is after this convert b64 := Base64EncodeBytes(dest); ... now I verify the Base64EncodeBytes function. – acarlomagno Feb 10 '15 at 16:41
  • Perhaps then you could re-write the question to be about base64. And provide complete programs that we can use directly. – David Heffernan Feb 11 '15 at 07:30
  • I don't know if I used a correct way ... but if I convert the Bytes Value in String ... and I use this Base64Encode ... http://stackoverflow.com/questions/14411975/simple-code-to-encrypt-an-ini-file-string-using-a-password now I encrypt correctly. this is the example: SetString(stringValue, PAnsiChar(@dest[0]), slen); result := Base64Encode2(stringValue); – acarlomagno Feb 11 '15 at 22:10

1 Answers1

2

I don't know if I used a correct way ... but if I convert the Bytes Value in String and I use this Base64Encode in this link:

Simple code to encrypt an .INI file string using a password

now I encrypt correctly. this is the example:

SetString(stringValue, PAnsiChar(@dest[0]), slen); 
result := Base64Encode2(stringValue);
Community
  • 1
  • 1
acarlomagno
  • 79
  • 1
  • 2
  • 6
  • When are Delphi programmers going to learn that text and binary are not the same. That binary doesn't belong in strings. And that base64 encodes binary to text. – David Heffernan Feb 25 '15 at 07:43