我正在使用Delphi 2009,我在这里看到的大部分答案都是针对2010年以上的 我试图将加密(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), 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";
?>
答案 0 :(得分:8)
我认为有几个问题:-)
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,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";
?>
答案 1 :(得分:1)
谁是iv字节
$ivbytes = array(72, 163, 99, 62, 219, 111, 163, 114);
为密钥:test123456
$ivbytes = array(??, ??, ??, ??, ??, ??, ??, ??);
答案 2 :(得分:0)
我使用这种集成并取得了成功,但我无法提供更多信息,它属于我的雇主。
你是否初步确定了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);
别忘了在delphi中正确编码你的字符串,我使用Base64EncodeStr(Buffer);
我希望它有所帮助。