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;
}
在Delphi中:
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组件。即便如此,我还是没能正确解密。我尝试过使用字节数组作为参数、AnsiStrings、WideStrings 等,但不幸的是没有运气。
如果我在这里遗漏了一些非常明显的东西,请原谅,因为经过几个小时的搜索后,我的头脑状况不佳。
I have problems with decrypting strings sent from PHP to Delphi using the rijndael cipher.
I'm using mcrypt on the PHP side and DCP_rijndael on the Delphi side.
At the moment I have the below code.
PHP:
function encRJ($key, $iv, $data)
{
$r = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $data, MCRYPT_MODE_CBC, $iv);
$r = base64_encode($r);
return $r;
}
And in Delphi:
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;
I have tried using several Units on the Internet implementing the cipher, and found out most people are saying about the DCP components. Even so, I haven't managed to make it correctly decrypt. I've tried using Byte arrays for the parameters, AnsiStrings, WideStrings, etc, but unfortunately no luck.
Excuse me if I'm missing something really obvious here, as my mind isn't in good shape atm, after hours of searching for the matter.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我似乎在这方面花了太长时间但是......
你的问题是块大小。 TDCP_rijndael 相当于 MCRYPT_RIJNDAEL_128(不是 _256)。不过 ciph.Init(...) 调用中的“256”值仍然正确。除此之外它看起来还不错。也就是说,假设您使用 ansistrings 作为 key/iv 或者您使用非 unicode Delphi。
对于 unicode Delphi 版本,我倾向于使用 TBytes 和 key[0] / iv[0]。
填充可能仍然是一个问题。如果是这样,那么这就是我根据 PHP 手册页和一些试验和错误所修改的内容。
PHP:
Delphi:
PHP 和 Delphi 函数现在给了我相同的答案。
EDIT
Base64DecodeBytes 是我添加到 DCP Base64 单元中的一些代码:
EDIT 2018(复活死者...):
根据要求,这里是编码方法,未经检查并直接从旧源中提取我找到的文件。
免责声明:它已有很多的历史,在最近的记忆中未经测试,并且自 Delphi 2010 以来就没有使用过。现在可能有许多更好的替代方案。使用风险自负。
I seem to have spent too long on this but...
Your problem is the block size. TDCP_rijndael is equivalent to MCRYPT_RIJNDAEL_128 (not _256). The '256' value in ciph.Init(...) call is still correct though. Other than that it looks pretty much ok. That is, assuming you're using ansistrings for key/iv or you're using non-unicode Delphi.
For unicode Delphi versions I'd be inclined to use TBytes and key[0] / iv[0].
Padding may still be an issue. If so, then here's what I've mangled up based on the PHP manual pages and some trial and error.
PHP:
Delphi:
The PHP and Delphi functions now give me the same answer.
EDIT
Base64DecodeBytes was a bit of code I added to the DCP Base64 unit:
EDIT 2018 (Raising the dead...):
As requested, here is the encoding method, unchecked and pulled straight from an old source file I found.
DISCLAIMER: It is many years old and untested in recent memory and not used since Delphi 2010. There are probably many better alternatives now. Use at your own risk.
您的 PHP 和 Delphi 方法似乎都没有指定任何填充。如果默认填充不同,那么您将会遇到问题。为两者显式指定 PKCS7(或 PKCS5)。
GregS 对 Base64 解码结果的评论是正确的。您正在向 decRJ() 方法提供加密的密文。这将是随机出现的字节。尝试将其转换为 UTF-8 会严重破坏它,导致无法解密。传入的密文必须从 Base64 直接转换为字节数组。密文不是字符串,这就是为什么它需要转换为 Base64 才能作为文本传输。 在解密回纯文本后,它才会再次成为文本。
Neither your PHP nor your Delphi methods appear to specify any padding. If the default paddings are different then you will get problems. Explicitly specify PKCS7 (or PKCS5) for both.
GregS' comment about the result of decoding Base64 is correct. You are supplying encrypted cyphertext to your decRJ() method. That will be random appearing bytes. Attempting to convert it to UTF-8 will mangle it enough that it cannot be decrypted. The incoming cyphertext must be converted from Base64 direct to a byte array. Cyphertext is not a character string, which is why it needs to be converted to Base64 to be transmitted as text. It will only be text again after it has been decrypted back to plaintext.