Don't do this:
byte[] bytes = data.getBytes();
That will use the platform default encoding to convert a string to a byte array. That can vary between platform, whereas you want something repeatable. I would suggest UTF-8:
byte[] bytes = data.getBytes("UTF-8");
(Do the same for the key, of course.)
You should then use the same encoding in your C# - not ASCII, unless you really want to not handle non-ASCII characters.
byte[] bytes = Encoding.UTF8.GetBytes(data);
It's also not clear how you're comparing the results afterwards - don't forget that byte
is signed in Java, but unsigned in C#. It's probably simplest to convert the hash to hex or base64 for comparison purposes.
EDIT: I strongly suspect the last part was the problem - comparing the results.
Here are two short but complete programs (using the iharder.net base64 converter in Java) which produce the same base64 output:
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));
}
}
Output from both:
ivEyFpkagEoghGnTw/LmfhDOsiNbcnEON50mFGzW9/w=
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…