简体   繁体   English

Java MD5哈希不匹配.NET哈希

[英]Java MD5 Hash Not Matching .NET Hash

I have a webservice that is written in C# handling some validation of values. 我有一个用C#编写的web服务处理一些值的验证。 In it I need to check a MD5 hash generated in the calling Java client. 在其中我需要检查在调用Java客户端中生成的MD5哈希。

The Java client generates the hash in this manner 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);

The C# webservice generates its has in this manner: C#webservice以这种方式生成它:

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. 我在Java代码中尝试了几个字符集,但它们都没有产生任何类似于Java生成的字符串的字符串。 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. 使用在每次调用期间相同的硬编码值(意味着我已经对参数进行了硬编码以使哈希值匹配)仍会产生奇怪的Java字符串。

C# Example of hashed values: C#散列值示例:

6wM7McddLBjofdFJ3rU6/g== 6wM7McddLBjofdFJ3rU6 /克==

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. 我发布了Java产生的字符串示例,但它有一些非常奇怪的字符,我认为我不能在这里粘贴。

What am I doing wrong? 我究竟做错了什么?

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. 永远不会尝试通过将任意二进制数据传递给String构造函数来对其进行编码。 Always use base64, or hex, or something like that. 始终使用base64或hex,或类似的东西。 Apache Commons Codec has a Base64 encoder, or this public domain version has a slightly more pleasant API. Apache Commons Codec有一个Base64编码器,或者这个公共域版本有一个稍微令人愉快的API。

The equivalent C# would be: 等效的C#将是:

// 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? MD5摘要生成的二进制数据实际上是一个有效的UTF-8字节序列的几率是多少?

Two other things to note: 还有两点需要注意:

  • You can get hold of an MD5 hash slightly more simply in .NET using the MD5 class: 您可以使用MD5类在.NET中稍微更简单地获取MD5哈希:

     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. 注意事后using语句来处理实例。 My main preference for this is that it's easier to remember, read and type MD5 than MD5CryptoServiceProvider :) 我对此的主要偏好是,它比MD5CryptoServiceProvider更容易记住,读取和输入MD5 :)

  • You haven't made it clear what _StringEncoding is, but the code should really just use Encoding.UTF8 to match the Java. 你还没有说清楚_StringEncoding是什么,但代码应该只使用Encoding.UTF8来匹配Java。

Your C# digest is in Base64, but your Java digest is not. 您的C#摘要在Base64中,但您的Java摘要不是。 Convert thedigest to Base64 as well. thedigest转换为Base64。

In C#, you encode the bytes using Base64. 在C#中,使用Base64对字节进行编码。 In Java, you interpret the bytes as a UTF-8-string. 在Java中,您将字节解释为UTF-8字符串。

Your C# code outputs MD5 hash as BASE64-encoded, but java code does not. 您的C#代码将MD5哈希输出为BASE64编码,但java代码不会。 A generic method to compare two MD5 hashes is to compare its hexadecimal presentation (16bytes -> 32digits). 比较两个MD5哈希的通用方法是比较其十六进制表示(16bytes - > 32digits)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM