Java MD5 哈希与 .NET 哈希不匹配

发布于 2024-10-26 19:16:30 字数 970 浏览 2 评论 0原文

我有一个用 C# 编写的 Web 服务,处理一些值的验证。在其中我需要检查调用 Java 客户端中生成的 MD5 哈希值。

Java 客户端以这种方式生成哈希

Charset utf8Charset = Charset.forName("UTF-8");

byte[] bytesOfPhrase = phrase.getBytes(utf8Charset);
MessageDigest md = MessageDigest.getInstance("MD5");

byte[] thedigest = md.digest(bytesOfPhrase);
this._AuthenticationToken = new String(thedigest, utf8Charset);

C# Web 服务以这种方式生成它的哈希值:

private static string HashString(string toHash)
{
    MD5CryptoServiceProvider md5Provider = new MD5CryptoServiceProvider();

    byte[] hashedBytes = md5Provider.ComputeHash(_StringEncoding.GetBytes(toHash));
    return Convert.ToBase64String(hashedBytes);
}

我在 Java 代码中尝试了几种字符集,但它们都没有生成与 Java 生成的字符串相似的字符串。使用每次调用期间都相同的硬编码值(意味着我对参数进行了硬编码,以便哈希值应该匹配)仍然会产生奇怪的 Java 字符串。

C# 哈希值示例:

6wM7McddLBjofdFJ3rU6/g==

我会发布 Java 生成的字符串的示例,但它有一些非常奇怪的字符,我认为我无法粘贴到这里。

我做错了什么?

I have a webservice that is written in C# handling some validation of values. In it I need to check a MD5 hash generated in the calling Java client.

The Java client generates the hash in this manner

Charset utf8Charset = Charset.forName("UTF-8");

byte[] bytesOfPhrase = phrase.getBytes(utf8Charset);
MessageDigest md = MessageDigest.getInstance("MD5");

byte[] thedigest = md.digest(bytesOfPhrase);
this._AuthenticationToken = new String(thedigest, utf8Charset);

The C# webservice generates its has in this manner:

private static string HashString(string toHash)
{
    MD5CryptoServiceProvider md5Provider = new MD5CryptoServiceProvider();

    byte[] hashedBytes = md5Provider.ComputeHash(_StringEncoding.GetBytes(toHash));
    return Convert.ToBase64String(hashedBytes);
}

I've tried several charsets in the Java code, but none of them produce a string that is anywhere similar to the Java produced string. Using hard coded values that are the same during every call (meaning that I've hardcoded the parameters so the hashes should match) still produces an odd Java string.

C# Example of hashed values:

6wM7McddLBjofdFJ3rU6/g==

I'd post the example of the string Java produces, but it has some very odd characters that I do not think I can paste in here.

What am I doing wrong?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

沫离伤花 2024-11-02 19:16:30

从根本上来说,这是一个损坏的代码:

// Badly broken
byte[] thedigest = md.digest(bytesOfPhrase);
this._AuthenticationToken = new String(thedigest, utf8Charset);

永远、永远、永远不会尝试通过将任意二进制数据传递给 String 构造函数来对其进行编码。 始终使用base64、十六进制或类似的东西。 Apache Commons Codec 有一个 Base64 编码器,或者这个 公共域版本有一个稍微更令人愉快的API。

等效的 C# 是:

// Equally broken
byte[] hashedBytes = md5Provider.ComputeHash(Encoding.UTF8.GetBytes(toHash));
return Encoding.UTF8.GetString(hashedBytes);

MD5 摘要生成的二进制数据实际上是有效的 UTF-8 字节序列的可能性有多大?

另外两件事需要注意:

  • 您可以使用 MD5 类在 .NET 中更简单地获取 MD5 哈希值:

    byte[] 哈希;
    使用 (MD5 md5 = MD5.Create())
    {
        哈希 = md5.ComputeHash(字节);
    }
    // 使用哈希
    

    请注意随后使用 using 语句来处理实例。我对此的主要偏好是它比 MD5CryptoServiceProvider 更容易记住、阅读和输入 MD5 :)

  • 您还没有弄清楚 _StringEncoding< /code> 是,但代码实际上应该只使用 Encoding.UTF8 来匹配 Java。

This is fundamentally broken code:

// Badly broken
byte[] thedigest = md.digest(bytesOfPhrase);
this._AuthenticationToken = new String(thedigest, utf8Charset);

Never, ever, ever try to encode arbitrary binary data by passing it to the String constructor. Always use base64, or hex, or something like that. Apache Commons Codec has a Base64 encoder, or this public domain version has a slightly more pleasant API.

The equivalent C# would be:

// Equally broken
byte[] hashedBytes = md5Provider.ComputeHash(Encoding.UTF8.GetBytes(toHash));
return Encoding.UTF8.GetString(hashedBytes);

What are the chances that the binary data produced by an MD5 digest is actually a valid UTF-8 byte sequence?

Two other things to note:

  • You can get hold of an MD5 hash slightly more simply in .NET using the MD5 class:

    byte[] hash;
    using (MD5 md5 = MD5.Create())
    {
        hash = md5.ComputeHash(bytes);
    }
    // Use hash
    

    Note the use of the using statement to dispose of the instance afterwards. My main preference for this is that it's easier to remember, read and type MD5 than MD5CryptoServiceProvider :)

  • You haven't made it clear what _StringEncoding is, but the code should really just use Encoding.UTF8 to match the Java.

谜兔 2024-11-02 19:16:30

您的 C# 摘要采用 Base64,但您的 Java 摘要不是。将 thedigest 也转换为 Base64。

Your C# digest is in Base64, but your Java digest is not. Convert thedigest to Base64 as well.

无人问我粥可暖 2024-11-02 19:16:30

在 C# 中,您使用 Base64 对字节进行编码。在 Java 中,您将字节解释为 UTF-8 字符串。

In C#, you encode the bytes using Base64. In Java, you interpret the bytes as a UTF-8-string.

Bonjour°[大白 2024-11-02 19:16:30

您的 C# 代码将 MD5 哈希输出为 BASE64 编码,但 Java 代码不会。
比较两个 MD5 哈希值的通用方法是比较其十六进制表示形式(16 字节 -> 32 位数字)。

Your C# code outputs MD5 hash as BASE64-encoded, but java code does not.
A generic method to compare two MD5 hashes is to compare its hexadecimal presentation (16bytes -> 32digits).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文