我有一个用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);
Run Code Online (Sandbox Code Playgroud)
C#webservice以这种方式生成它:
private static string HashString(string toHash)
{
MD5CryptoServiceProvider md5Provider = new MD5CryptoServiceProvider();
byte[] hashedBytes = md5Provider.ComputeHash(_StringEncoding.GetBytes(toHash));
return Convert.ToBase64String(hashedBytes);
}
Run Code Online (Sandbox Code Playgroud)
我在Java代码中尝试了几个字符集,但它们都没有产生任何类似于Java生成的字符串的字符串.使用在每次调用期间相同的硬编码值(意味着我已经对参数进行了硬编码以使哈希值匹配)仍会产生奇怪的Java字符串.
C#散列值示例:
6wM7McddLBjofdFJ3rU6 /克==
我发布了Java产生的字符串示例,但它有一些非常奇怪的字符,我认为我不能在这里粘贴.
我究竟做错了什么?
这基本上是破码:
// Badly broken
byte[] thedigest = md.digest(bytesOfPhrase);
this._AuthenticationToken = new String(thedigest, utf8Charset);
Run Code Online (Sandbox Code Playgroud)
永远不会尝试通过将任意二进制数据传递给String构造函数来对其进行编码.始终使用base64或hex,或类似的东西.Apache Commons Codec有一个Base64编码器,或者这个公共域版本有一个稍微令人愉快的API.
等效的C#将是:
// Equally broken
byte[] hashedBytes = md5Provider.ComputeHash(Encoding.UTF8.GetBytes(toHash));
return Encoding.UTF8.GetString(hashedBytes);
Run Code Online (Sandbox Code Playgroud)
MD5摘要生成的二进制数据实际上是一个有效的UTF-8字节序列的几率是多少?
还有两点需要注意:
您可以使用MD5
类在.NET中稍微更简单地获取MD5哈希:
byte[] hash;
using (MD5 md5 = MD5.Create())
{
hash = md5.ComputeHash(bytes);
}
// Use hash
Run Code Online (Sandbox Code Playgroud)
注意using
事后使用该语句来处理实例.我对此的主要偏好是它MD5
比MD5CryptoServiceProvider
:) 更容易记忆,阅读和输入
你还没说清楚它是什么_StringEncoding
,但是代码应该只是Encoding.UTF8
用来匹配Java.