C#和Java-hmacsha256哈希之间的区别
问题内容:
我在Java中有以下代码:
byte[] secretKey = secretAccessKey.getBytes("UTF-8");
SecretKeySpec signingKey = new SecretKeySpec(secretKey, "HmacSHA256");
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(signingKey);
byte[] bytes = data.getBytes("UTF-8");
byte[] rawHmac = mac.doFinal(bytes);
String result = javax.xml.bind.DatatypeConverter.printBase64Binary(rawHmac);
以及C#中的以下代码:
UTF8Encoding enc = new UTF8Encoding();
byte[] secretKey = enc.GetBytes(secretAccessKey);
HMACSHA256 hmac = new HMACSHA256(secretKey);
hmac.Initialize();
byte[] bytes = enc.GetBytes(data);
byte[] rawHmac = hmac.ComputeHash(bytes);
string result = Convert.ToBase64String(rawHmac);
字节数组“ secretKey”和“ bytes”是等效的,但字节数组“ rawHmac”不同,字符串“ result”不同。谁能看到原因?
问题答案:
不要这样做:
byte[] bytes = data.getBytes();
这将使用平台默认编码将字符串转换为字节数组。平台之间可能会有所不同,而您想要一些可重复的东西。我建议使用UTF-8:
byte[] bytes = data.getBytes("UTF-8");
(当然,对密钥执行相同的操作。)
然后,您应该在C#中使用相同的编码- 而不是 ASCII,除非您确实不想处理非ASCII字符。
byte[] bytes = Encoding.UTF8.GetBytes(data);
还不清楚您随后如何比较结果-别忘byte
了Java 中已签名,而C#中未签名。为了进行比较,将哈希转换为十六进制或base64可能是最简单的。
编辑:我强烈怀疑最后一部分是问题-比较结果。
这是两个简短但完整的程序(使用Java中的iharder.net base64转换器),它们产生相同的base64输出:
Java:
import java.util.*;
import javax.crypto.*;
import javax.crypto.spec.*;
public class Test {
public static void main (String[] args) throws Exception {
String secretAccessKey = "mykey";
String data = "my data";
byte[] secretKey = secretAccessKey.getBytes();
SecretKeySpec signingKey = new SecretKeySpec(secretKey, "HmacSHA256");
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(signingKey);
byte[] bytes = data.getBytes();
byte[] rawHmac = mac.doFinal(bytes);
System.out.println(Base64.encodeBytes(rawHmac));
}
}
C#:
using System;
using System.Security.Cryptography;
using System.Text;
class Test
{
static void Main()
{
String secretAccessKey = "mykey";
String data = "my data";
byte[] secretKey = Encoding.UTF8.GetBytes(secretAccessKey);
HMACSHA256 hmac = new HMACSHA256(secretKey);
hmac.Initialize();
byte[] bytes = Encoding.UTF8.GetBytes(data);
byte[] rawHmac = hmac.ComputeHash(bytes);
Console.WriteLine(Convert.ToBase64String(rawHmac));
}
}
两者的输出:
ivEyFpkagEoghGnTw/LmfhDOsiNbcnEON50mFGzW9/w=