我正在使用Delphi 2009,我在这里看到的大多数答案都是针对2010年的
我试图将加密(delphi)同步到解密(PHP)并失败.
我试图将加密(delphi)同步到解密(PHP)并失败.
在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.
在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),$block); $str = mcrypt_decrypt(MCRYPT_DES,$k,$data,MCRYPT_MODE_CBC,$iv); $pad = ord($str[($len = strlen($str)) - 1]); return substr($str,strlen($str) - $pad); } $enc = 'TW5mbVFhODUyR2FoOTA2WWJIOD0='; $dec = decrypt($enc,'test'); echo "$dec\n"; ?>
解决方法
我认为有几个问题:-)
> des.InitStr()在内部从8个空字节创建一个IV然后加密.您需要在PHP中使用相同的IV.
> sha1($key)生成十六进制字符串而不是密码的实际字节.你需要像mhash这样的东西.
>我无法使用给定的Delphi函数重现您的$enc字符串.
> Unicode问题 – 在Delphi中,密码和源文本将被视为unicode.
>您似乎是在Delphi例程中对源进行两次编码. des.EncryptString和des.DecryptString生成并使用base 64编码的字符串,因此无需再次执行.
>填充
基于我以前的答案here – 这是我的建议:
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;
和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) encrypted using ECB mode and gives the // following bytes: $ivbytes = array(72,163,99,62,219,111,114); $iv = implode(array_map("chr",$ivbytes)); $enc = base64_decode($str); $k = mhash(MHASH_SHA1,$key); $dec = mcrypt_decrypt(MCRYPT_DES,substr($k,$keysize),$enc,$iv); $pad = ord($dec[strlen($dec) - 1]); return substr($dec,strlen($dec) - $pad); } $enc = 'WRaG/8xlxqqcTAJ5UAk4DA=='; $dec = decrypt_SO($enc,'test'); echo "$dec\n"; ?>