user3024750 user3024750 - 1 year ago 164
C# Question

HMAC-SHA256 in Java/ Translate from C#

I have this piece of code in C#:

byte[] bytes = Encoding.Default.GetBytes("secret key");
int value = checked((int)Math.Round((currentDateTime - dateTimeOf1970).TotalSeconds));
HMACSHA256 hMACSHA = new HMACSHA256(bytes);
string text2 = this.toHexString(hMACSHA.ComputeHash(Encoding.Default.GetBytes(value.ToString() + "/" + url)));

where the method toHexString is this:

private string toHexString (byte[] bytes)
string text = "";
for (int i = 0; i < bytes.Length; i++)
byte b = bytes[i];
int num = (int)b;
string text2 = num.ToString("X").ToLower();
if (text2.Length < 2)
text2 = "0" + text2;
text += text2;
return text;

Now I'd like to have that in Java, and as my Java skills are not as well as my C# skills I'm figuring out how to translate it. The toHexString method I translated like this:

private static String toHexString (byte[] bytes) {
String text = "";
for (int i = 0; i < bytes.length; i++) {
byte b = bytes[i];
int num = (int) b;
String text2 = Integer.toHexString(num);
if (text2.length() < 2) {
text2 = "0" + text2;
text += text2;


return text;


This works very well, produces the same output as the C# version.

Now to the other method (with the HMCAS-SHA256), thats my go on translating it:

//creating the timestamp
long timestamp = System.currentTimeMillis() / 1000;
//getting the int value of it
int value = (int) timestamp;

//just a string that is the value of the hmac
String input = String.valueOf(value) + "/" + url;
//new hmac instance
Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
//my secret key where bytes is "my key".getBytes();
SecretKeySpec secret_key = new SecretKeySpec(bytes, "HmacSHA256");
//trying to have as string
String txt2 = toHexString (sha256_HMAC.doFinal(input.getBytes()));

Problem is that it doesnt produce the same output,

C# version (how it should be):


Java version:


Any help would be appreciated!

Answer Source

Your main problem is that your Java toHexString() method is screwed up.

Java is always working with signed values, therefore Integer.toHexString(num); returns a lot of negative 32-bit numbers (you can see the ff in the output.

Therefore if you convert a byte to an (unsigned) int you always have to add & 0xFF:

Integer.toHexString(0xff & num);

Anyway a byte-array-to-hex-string method is available in a lot of libraries. Therefore it is not necessary to code it again. I prefer the Hex class from apache commons codec library.

BTW: You are using the default encoding in C# and Java but even on the same machine this does not necessarily means the encoding is the same. Use a fixed one like UTF-8 instead.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download