how to sync encryption between delphi and php usin

2020-02-26 03:14发布

I'm using Delphi 2009 and most of the answers I've seen here are for 2010+ I am trying to sync encryption (delphi) to decryption (php) and failing.

generate the encrypted string in delphi:

program Project4;

{$APPTYPE CONSOLE}

uses
  SysUtils,
  DCPcrypt2,
  DCPsha1,
  DCPblockciphers,
  DCPdes,
  EncdDecd;

var des: tdcp_des;
    enc,dec: ansistring;

begin
  try
  des:=tdcp_des.Create(nil);
  des.InitStr('test', tdcp_sha1);
  enc:=encodestring(des.EncryptString('this is a test'));
  des.Free;

  des:=tdcp_des.Create(nil);
  des.InitStr('test', tdcp_sha1);
  dec:=des.DecryptString(decodestring(enc));
  des.Free;

  writeln(enc);
  writeln(dec);
  except
    on E:Exception do
      Writeln(E.Classname, ': ', E.Message);
  end;
end.

decrypt in php:

<?php
function decrypt($str, $key)
{
    $size = mcrypt_get_iv_size(MCRYPT_DES, MCRYPT_MODE_CBC);
    $iv = mcrypt_create_iv($size, MCRYPT_DEV_RANDOM);
    $data = base64_decode($str);
    $block = mcrypt_get_block_size('des', 'ecb');
    $k = substr(sha1($key), 0, $block);
    $str = mcrypt_decrypt(MCRYPT_DES, $k, $data, MCRYPT_MODE_CBC, $iv);
    $pad = ord($str[($len = strlen($str)) - 1]);
    return substr($str, 0, strlen($str) - $pad);
}

$enc = 'TW5mbVFhODUyR2FoOTA2WWJIOD0=';
$dec = decrypt($enc, 'test');
echo "$dec\n";
?>

3条回答
一夜七次
2楼-- · 2020-02-26 04:04

Several issues, I think :-)

  • des.InitStr() internally creates an IV from 8 null bytes which it then encrypts. You need to use the same IV in your PHP.

  • The sha1($key) produces a hex string rather than the actual bytes of the password. You need something like mhash instead.

  • I couldn't manage to reproduce your $enc string with the given Delphi function.

  • Unicode issues - the password and source text are going to be treated as unicode in Delphi.

  • You seem to be base 64 encoding the source twice in the Delphi routines. des.EncryptString and des.DecryptString produce and consume base 64 encoded strings so no need to do it again.

  • Padding

Based on my previous answer here - this is my suggestion:

function EncryptStringDES: string;
var
  des: TDCP_des;
  src, enc, b64: TBytes;
  index, slen, bsize, padsize: integer;
begin
  des:=tdcp_des.Create(nil);
  try
    des.InitStr(AnsiString('test'), tdcp_sha1);

    src := TEncoding.UTF8.GetBytes('this is a test');
    slen := Length(src);
    // Add padding
    bsize := des.BlockSize div 8;
    padsize := bsize - (slen mod bsize);
    Inc(slen, padsize);
    SetLength(src, slen);
    for index := padsize downto 1 do
    begin
      src[slen - index] := padsize;
    end;

    SetLength(enc, slen);
    des.EncryptCBC(src[0], enc[0], slen);
    result := EncdDecd.EncodeBase64(@enc[0], Length(enc));
  finally
    des.Free;
  end;
end;

function DecryptStringDES(ASource: string): string;
var
  des: TDCP_des;
  key, src, dec, b64: TBytes;
  pad, slen: integer;
begin
  des := TDCP_des.Create(nil);
  try
    des.InitStr(AnsiString('test'), tdcp_sha1);

    src := EncdDecd.DecodeBase64(AnsiString(ASource));
    slen := Length(src);
    SetLength(dec, slen);
    des.DecryptCBC(src[0], dec[0], slen);

    // Remove padding
    pad := dec[slen - 1];
    SetLength(dec, slen - pad);

    result := TEncoding.UTF8.GetString(dec);
  finally
    des.Free;
  end;
end;

and the PHP:

<?php
function decrypt_SO($str, $key)
{
    //$ivsize = mcrypt_get_iv_size(MCRYPT_DES, MCRYPT_MODE_CBC);
    //$blocksize = mcrypt_get_block_size(MCRYPT_DES, MCRYPT_MODE_CBC);
    $keysize = mcrypt_get_key_size(MCRYPT_DES, MCRYPT_MODE_CBC);

    // Need to use the SAME IV as the Delphi function. By default
    // this is (0,0,0,0,0,0,0,0) encrypted using ECB mode and gives the
    // following bytes:
    $ivbytes = array(72, 163, 99, 62, 219, 111, 163, 114);
    $iv = implode(array_map("chr", $ivbytes));

    $enc = base64_decode($str);
    $k = mhash(MHASH_SHA1, $key);
    $dec = mcrypt_decrypt(MCRYPT_DES, substr($k, 0, $keysize), $enc, MCRYPT_MODE_CBC, $iv);

    $pad = ord($dec[strlen($dec) - 1]);
    return substr($dec, 0, strlen($dec) - $pad);
}

$enc = 'WRaG/8xlxqqcTAJ5UAk4DA==';
$dec = decrypt_SO($enc, 'test');
echo "$dec\n";
?>
查看更多
Juvenile、少年°
3楼-- · 2020-02-26 04:11

i use this kind of integration with success but i cant provide more information than that, it belongs to my employer.

did you initialized mycrypt?

$iv = "nononono";
$key = "nononono";
$td = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, '');
mcrypt_generic_init($td, $key, $iv);
$decoded = base64_decode($mySecretString);
$decryptedcbc = mdecrypt_generic($td, $decoded);
mcrypt_generic_deinit($td);

dont forget to encode your string properly in delphi, i use Base64EncodeStr(Buffer);

i hope it helps.

查看更多
我想做一个坏孩纸
4楼-- · 2020-02-26 04:14

who is the iv bytes

$ivbytes = array(72, 163, 99, 62, 219, 111, 163, 114);

for the key: test123456

$ivbytes = array(??, ??, ??, ??, ??, ??, ??, ??);
查看更多
登录 后发表回答