如何在Delphi和PHP中获得相同的MD5?

8

我正在使用FireMonkey的Delphi XE2

我已经阅读了许多关于MD5的问题,但没有找到解决我的问题的答案......我还尝试了不同的脚本来从Delphi生成MD5:

function MD5(const text: string) : string;
var
  md5 : TIdHashMessageDigest5;
begin
  md5    := TIdHashMessageDigest5.Create;
  Result := LowerCase(md5.HashStringAsHex(text, TEncoding.ANSI));
  md5.Free;
end;

或者

function MD5(const text: String) : string;
var
  md5: IMD5;
begin
  md5:= GetMD5;
  md5.Init;
  md5.Update(TByteDynArray(RawByteString(AnsiString(text))), Length(AnsiString(text)));
  Result := LowerCase(md5.AsString);
end;

两者都给我相同的结果...通常与我在PHP中得到的结果相同:

$md5 = md5($toencode);
$md5 = hash("md5", $toencode);

但是,如果我使用Delphi或PHP请求这些字符之一的MD5时,结果会有所不同:"'。也许还有其他生成不同结果的字符,但在我的测试中,我只发现了这些...

我已经尝试了许多扩展ASCII字符,并且得到了相同的MD5值...

所以,我不明白为什么其中一些字符("')会有差异,我想知道是否有一种方法可以从Delphi始终生成与PHP MD5结果相同的结果,无论字符是什么。

有什么想法吗?

例如:

使用Delphi

": b15835f133ff2e27c7cb28117bfae8f4

': 3590cb8af0bbb9e78c343b52b93773c9

使用PHP

": 3bd864034f446da13581129bb17f9191

': 024c94d6e03b6f67a86b952b914816c7

总结这个问题... 我已经找到了答案... 顺便说一下,我将其发布出来,因为其他人可能也有同样的问题...

"' 在PHP中是转义的... 因此,在Delphi中,我必须编码 \"\'... 如果您认为我已经忘记了某些字符或者想要添加一些细节,请不要犹豫...


1
在对字符串进行 MD5 加密之前,你可以在 PHP 中运行 stripslashes。 - Jason
1
是的...但是... ;o) 我正在访问一个远程服务器,我没有访问代码的权限... - Whiler
2
PHP转义引号、双引号、反斜杠和“NUL”(在Delphi中为#0),请参见http://www.php.net/manual/en/security.magicquotes.what.php。 - Stijn Sanders
1
你不是在字符串上计算散列值,而是在二进制数据上计算。现在去坐到某个地方,把这个写下来100遍。 - Jeroen Wiert Pluimers
@JeroenWiertPluimers:我同意你的观点...但是当一个API要求MD5密码时...为了使用API...你需要做出一些妥协 ;) - Whiler
1
然后,您必须确保密码在两端以相同的二进制方式进行编码。这是您问题的关键所在。MD5的唯一相关性在于它显示您的编码错误。在这种情况下:因为您转义了不应该转义的内容。 - Jeroen Wiert Pluimers
3个回答

6

Delphi 在这里是正确的。

>>> hashlib.md5('"').hexdigest()
'b15835f133ff2e27c7cb28117bfae8f4'
>>> hashlib.md5("'").hexdigest()
'3590cb8af0bbb9e78c343b52b93773c9'

默认情况下,PHP不需要对这些字符进行转义;确保其配置为不进行转义。


@David:我很确定。这就是为什么我怀疑字符被不必要地“转义”的原因。 - Ignacio Vazquez-Abrams
@IgnacioVazquez-Abrams 实际上这是一种相当奇怪的转义。不是我本来猜测的 URL 转义。 - David Heffernan

3

PHP的hash函数完美地实现了MD5。

以下是PHP示例:

$md5 = hash("md5", "\"");
echo "\":&nbsp;&nbsp;", $md5, "<br/>";
$md5 = hash("md5", "'");
echo "':&nbsp;&nbsp;", $md5, "<br/>";
$md5 = hash("md5", "\\\"");
echo "\\\": ", $md5, "<br/>";
$md5 = hash("md5", "\\'");
echo "\\': ", $md5, "<br/>";

以下是输出结果:

":  b15835f133ff2e27c7cb28117bfae8f4
':  3590cb8af0bbb9e78c343b52b93773c9
\": 3bd864034f446da13581129bb17f9191
\': 024c94d6e03b6f67a86b952b914816c7

因此,前两个值是您从Delphi代码中获得的值,也是Ignacio从Python获得的相同值。所以,绝对没有理由认为PHP MD5代码有问题。而后两个值是您的PHP代码返回的。

这意味着您向Delphi代码提供的输入与您向PHP代码提供的输入不同。如果您向它们都提供相同的输入,则会获得相同的输出。


是的,我的错... @StijnSanders的URL向我解释了原因... 我的测试失败是因为从“表单”中填充的变量被破坏了(自动转义反斜杠)。 - Whiler

1
    uses IdHashMessageDigest;

    function MD5(const texto:string):string;
    var
      idmd5 : TIdHashMessageDigest5;
    begin
      idmd5 := TIdHashMessageDigest5.Create;
      try
        result := idmd5.HashStringAsHex(UTF8Encode(texto));
      finally
        idmd5.Free;
      end;
    end;

使用 LowerCase(MD5('1234')); 可以完全相同地使用 PHP MD5。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接