Java和c#上的SHA-1哈希
本文关键字:SHA-1 哈希 上的 Java | 更新日期: 2023-09-27 18:13:22
我试图用SHA-1验证XML节点的内容,基本上,我们用该节点的内容生成SHA-1哈希,双方(客户端c#和服务器端Java)应该具有完全相同的哈希。
问题是,我已经用diff工具检查了两个文本的内容,没有任何差异。但是我得到的哈希值与客户端不同。
c# hash: 60-53-58-69-29-EB-53-BD-85-31-79-28-A0-F9-42-B6-DE-1B-A6-0A
Java hash: E79D7E6F2A6F5D776447714D896D4C3A0CBC793
客户端(c#)生成哈希值的方式如下:
try
{
Byte[] stream = null;
using (System.Security.Cryptography.SHA1CryptoServiceProvider shaProvider = new System.Security.Cryptography.SHA1CryptoServiceProvider())
{
stream = shaProvider.ComputeHash(System.Text.Encoding.UTF8.GetBytes(text));
if (stream == null)
{
hash = "Error";
}
else
{
hash = System.BitConverter.ToString(stream);
}
}
}
catch (Exception error)
{
hash = string.Format("Error SHA-1: {0}", error);
}
return hash;
,服务器(Java)是这样生成哈希的:
byte[] key = content.getBytes();
MessageDigest md = MessageDigest.getInstance("SHA1");
byte[] hash = md.digest(key);
String result = "";
for (byte b : hash) {
result += Integer.toHexString(b & 255);
}
return result.toUpperCase();
有人能帮帮我吗?.. 谢谢:)
更新:为了检查发生了什么,我检查了在c#中获得SHA1哈希的其他方法,我发现了这个:
/// <summary>
/// Compute hash for string encoded as UTF8
/// </summary>
/// <param name="s">String to be hashed</param>
/// <returns>40-character hex string</returns>
public static string SHA1HashStringForUTF8String(string s)
{
byte[] bytes = Encoding.UTF8.GetBytes(s);
using (var sha1 = SHA1.Create())
{
byte[] hashBytes = sha1.ComputeHash(bytes);
return System.BitConverter.ToString(hashBytes).Replace("-",string.Empty);
}
}
下面的代码给出如下输出:
E79D07E6F2A6F5D776447714D896D4C3A0CBC793
和! !我只是注意到Python给出了相同的输出(对不起,我应该仔细检查一下)
就是这样
使用此提供程序:System.Security.Cryptography.SHA1CryptoServiceProvider shaProvider = new System.Security.Cryptography.SHA1CryptoServiceProvider()
在三台不同的机器上给出完全不同的输出。
在 c#中使用上述方法得到与python 相同的结果,同时,由于某些原因Java给出了一个稍微不同的输出:
E79D7E6F2A6F5D776447714D896D4C3A0CBC793
想法?Java是问题所在吗?字节十六进制方法上的Java是问题?还有别的选择吗?
尝试在c#中使用此散列:
static string Hash(string input)
{
using (SHA1Managed sha1 = new SHA1Managed())
{
var hash = sha1.ComputeHash(Encoding.UTF8.GetBytes(input));
var sb = new StringBuilder(hash.Length * 2);
foreach (byte b in hash)
{
// can be "x2" if you want lowercase
sb.Append(b.ToString("x2"));
}
return sb.ToString();
}
}
Hash("test"); //a94a8fe5ccb19ba61c4c0873d391e987982fbbd3
然后使用这个作为你的Java散列:
private static String convertToHex(byte[] data) {
StringBuilder buf = new StringBuilder();
for (byte b : data) {
int halfbyte = (b >>> 4) & 0x0F;
int two_halfs = 0;
do {
buf.append((0 <= halfbyte) && (halfbyte <= 9) ? (char) ('0' + halfbyte) : (char) ('a' + (halfbyte - 10)));
halfbyte = b & 0x0F;
} while (two_halfs++ < 1);
}
return buf.toString();
}
public static String SHA1(String text) throws NoSuchAlgorithmException, UnsupportedEncodingException {
MessageDigest md = MessageDigest.getInstance("SHA-1");
byte[] textBytes = text.getBytes("iso-8859-1");
md.update(textBytes, 0, textBytes.length);
byte[] sha1hash = md.digest();
return convertToHex(sha1hash);
}
SHA1("test"); //a94a8fe5ccb19ba61c4c0873d391e987982fbbd3
注意,您需要以下导入:
import java.io.UnsupportedEncodingException; import
java.security.MessageDigest; import
java.security.NoSuchAlgorithmException;
抛出声明是选项,调整到最适合你的代码!
你的问题是你没有在两个API中散列相同的字节。
如果你选择修改java的版本,它应该是这样的:
byte[] key = content.getBytes("UTF8");
[...]
如果你选择修改c#的版本,它应该是这样的:
stream = shaProvider.ComputeHash(System.Text.Encoding.UTF16.GetBytes(text));
[...]
无论哪种方式,两个api都应该通过相同的编码获得密钥的字节。