delphi php 加解密,PHP到Delphi并使用Rijndael返回加密 – 解密

我使用rijndael密码解密从PHP发送到Delphi的字符串时遇到问题.

我在PHP端使用mcrypt,在Delphi端使用DCP_rijndael.

目前我有以下代码.

PHP:

function encRJ($key, $iv, $data)

{

$r = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $data, MCRYPT_MODE_CBC, $iv);

$r = base64_encode($r);

return $r;

}

在德尔福:

function decRJ(Data: string; Key: string; IV: string): string;

var ciph: TDCP_rijndael;

begin

Data := Base64DecodeStr(Data);

ciph:= TDCP_rijndael.Create(Self);

ciph.Init(Key[1], 256, @IV[1]);

ciph.DecryptCBC(Data[1], Data[1], Length(Data));

ciph.Free;

Result := Data;

end;

我尝试在互联网上使用几个单元来实现密码,并且发现大多数人都在谈论DCP组件.即便如此,我还是没有设法正确解密.我已经尝试使用Byte数组作为参数,AnsiStrings,WideStrings等,但遗憾的是没有运气.

对不起,如果我在这里遗漏了一些非常明显的东西,因为在经过几个小时的搜索之后,我的思维状态并不理想.

解决方法:

我似乎花了太长时间才这个……但是……

你的问题是块大小. TDCP_rijndael相当于MCRYPT_RIJNDAEL_128(不是_256). ciph.Init(…)调用中的’256’值仍然是正确的.除此之外,它看起来非常好.也就是说,假设您正在使用ansistrings for key / iv或者您正在使用非unicode Delphi.

对于unicode Delphi版本,我倾向于使用TBytes和key [0] / iv [0].

填充可能仍然是一个问题.如果是这样,那么这就是我基于PHP手册页和一些反复试验而破坏的内容.

PHP:

function Encrypt($src, $key, $iv)

{

$block = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, 'cbc');

//echo "Block size: " . $block . "\r\n";

$pad = $block - (strlen($src) % $block);

$src .= str_repeat(chr($pad), $pad);

$enc = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $src, MCRYPT_MODE_CBC, $iv);

$r = base64_encode($enc);

return $r;

}

function Decrypt($src, $key, $iv)

{

$enc = base64_decode($src);

$dec = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $enc, MCRYPT_MODE_CBC, $iv);

$block = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, 'cbc');

$pad = ord($dec[($len = strlen($dec)) - 1]);

return substr($dec, 0, strlen($dec) - $pad);

}

德尔福:

function DecryptData(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;

function EncryptData(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.UTF8.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;

PHP和Delphi函数现在给出了相同的答案.

编辑

Base64DecodeBytes是我添加到DCP Base64单元的一些代码:

function Base64DecodeBytes(Input: TBytes): TBytes;

var

ilen, rlen: integer;

begin

ilen := Length(Input);

SetLength(result, (ilen div 4) * 3);

rlen := Base64Decode(@Input[0], @result[0], ilen);

// Adjust the length of the output buffer according to the number of valid

// b64 characters

SetLength(result, rlen);

end;

编辑2018年(提升死者……):

根据要求,这是编码方法,取消选中并直接从我找到的旧源文件中提取.

免责声明:它已有很多年的历史,在最近的记忆中没有经过测试,自Delphi 2010以来就没有使用过.现在可能有很多更好的选择.使用风险由您自己承担.

function Base64EncodeBytes(Input: TBytes): TBytes;

var

ilen: integer;

begin

ilen := Length(Input);

SetLength(result, ((ilen + 2) div 3) * 4);

Base64Encode(@Input[0], @result[0], ilen);

end;

标签:rijndael,php,encryption,delphi

来源: https://codeday.me/bug/20191001/1838376.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值