Java 和 C# 之间的不同 MD5
Different MD5 between Java and C#
我想比较同一文件中的 MD5 哈希值。该文件通过 HTTP POST 从 Android 作为 byte[] 发送,我还计算哈希值并从 .NET 服务器接收,我再次计算哈希值然后比较它们。
问题是对于同一个文件我得到了不同的哈希...
Java代码
FileInputStream fileInputStream = null;
byte[] bFile = new byte[(int) file.length()];
try {
fileInputStream = new FileInputStream(file);
fileInputStream.read(bFile);
} catch (Exception e) {
e.printStackTrace();
}
try {
MessageDigest md = MessageDigest.getInstance("MD5");
int read = 0;
while((read = fileInputStream.read(bFile)) != -1) {
md.update(bFile, 0, read);
}
fileInputStream.close();
byte[] mdBytes = md.digest();
StringBuffer sb = new StringBuffer();
for(int i=0; i < mdBytes.length; ++i) {
sb.append(Integer.toString((mdBytes[i] & 0xff) + 0x100, 16).substring(1));
}
// generated MD5 is d41d8cd98f00b204e9800998ecf8427e
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
C#代码
using (var md5 = MD5.Create())
{
using (var stream = File.OpenRead(filePath))
{
string hexString = ToHex(md5.ComputeHash(stream), false);
// Generated MD5 is d167df114a478809ef71fb7e10c40f8c
}
}
public string ToHex(byte[] bytes, bool upperCase)
{
StringBuilder result = new StringBuilder(bytes.Length * 2);
for (int i = 0; i < bytes.Length; i++)
result.Append(bytes[i].ToString(upperCase ? "X2" : "x2"));
return result.ToString();
}
更新
我已尝试将 Java 代码更改为
StringBuffer sb = new StringBuffer();
for(int i=0; i < mdBytes.length; ++i) {
sb.append(String.format("%02x", mdBytes[i]));
}
结果总是一样的...
首先,通过使用许多免费提供的工具中的一个(或多个)来计算 MD5 哈希并查看您的 C# 或 Java 代码是否正确(也许两者都是错误的,好的 :-)).
那我们拭目以待。
更新:
在 Java 的情况下,您正在将数据读入字节数组;之后你使用相同的流(已经是 EOF),因此永远不会调用 md.update
.
更新 2:
所以,写
[...]
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(bFile, 0 , bFile.length);
byte[] mdBytes = md.digest();
[...]
你基本上没问题。顺便说一句,将字节数组转换为十六进制字符串的有趣技术......:-)你可能想寻找更好的方法......
读取文件流后,必须返回到流的开头才能正确计算哈希值。
我想比较同一文件中的 MD5 哈希值。该文件通过 HTTP POST 从 Android 作为 byte[] 发送,我还计算哈希值并从 .NET 服务器接收,我再次计算哈希值然后比较它们。
问题是对于同一个文件我得到了不同的哈希...
Java代码
FileInputStream fileInputStream = null;
byte[] bFile = new byte[(int) file.length()];
try {
fileInputStream = new FileInputStream(file);
fileInputStream.read(bFile);
} catch (Exception e) {
e.printStackTrace();
}
try {
MessageDigest md = MessageDigest.getInstance("MD5");
int read = 0;
while((read = fileInputStream.read(bFile)) != -1) {
md.update(bFile, 0, read);
}
fileInputStream.close();
byte[] mdBytes = md.digest();
StringBuffer sb = new StringBuffer();
for(int i=0; i < mdBytes.length; ++i) {
sb.append(Integer.toString((mdBytes[i] & 0xff) + 0x100, 16).substring(1));
}
// generated MD5 is d41d8cd98f00b204e9800998ecf8427e
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
C#代码
using (var md5 = MD5.Create())
{
using (var stream = File.OpenRead(filePath))
{
string hexString = ToHex(md5.ComputeHash(stream), false);
// Generated MD5 is d167df114a478809ef71fb7e10c40f8c
}
}
public string ToHex(byte[] bytes, bool upperCase)
{
StringBuilder result = new StringBuilder(bytes.Length * 2);
for (int i = 0; i < bytes.Length; i++)
result.Append(bytes[i].ToString(upperCase ? "X2" : "x2"));
return result.ToString();
}
更新
我已尝试将 Java 代码更改为
StringBuffer sb = new StringBuffer();
for(int i=0; i < mdBytes.length; ++i) {
sb.append(String.format("%02x", mdBytes[i]));
}
结果总是一样的...
首先,通过使用许多免费提供的工具中的一个(或多个)来计算 MD5 哈希并查看您的 C# 或 Java 代码是否正确(也许两者都是错误的,好的 :-)).
那我们拭目以待。
更新:
在 Java 的情况下,您正在将数据读入字节数组;之后你使用相同的流(已经是 EOF),因此永远不会调用 md.update
.
更新 2:
所以,写
[...]
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(bFile, 0 , bFile.length);
byte[] mdBytes = md.digest();
[...]
你基本上没问题。顺便说一句,将字节数组转换为十六进制字符串的有趣技术......:-)你可能想寻找更好的方法......
读取文件流后,必须返回到流的开头才能正确计算哈希值。