Reputation: 4134
I'm trying to convert a java based code to c# as followed;
The original java code;
String str2 = "5f1fa09364a6ae7e35a090b434f182652ab8dd76:{\"expiration\": 1353759442.0991001, \"channel\": \"dreamhacksc2\", \"user_agent\": \".*"
Mac localMac = Mac.getInstance("HmacSHA1");
localMac.init(new SecretKeySpec("Wd75Yj9sS26Lmhve".getBytes(), localMac.getAlgorithm()));
String str3 = new BigInteger(1, localMac.doFinal(str2.getBytes())).toString(16);
Object[] arrayOfObject2 = new Object[2];
arrayOfObject2[0] = str3;
arrayOfObject2[1] = URLEncoder.encode(str2);
String str4 = String.format("%s:%s", arrayOfObject2);
And here is my WinRT based c# code
var token="5f1fa09364a6ae7e35a090b434f182652ab8dd76:{\"expiration\": 1353759442.0991001, \"channel\": \"dreamhacksc2\", \"user_agent\": \".*";
var encoding = new System.Text.UTF8Encoding();
var key = encoding.GetBytes("Wd75Yj9sS26Lmhve");
//var key = Convert.FromBase64String("Wd75Yj9sS26Lmhve");
var tokenData = encoding.GetBytes(token);
var result = HmacSha1(key, tokenData);
var hexString = new BigInteger(result).ToString("x");
var urlEncoded = System.Net.WebUtility.UrlEncode(token);
var combined = String.Format("{0}:{1}", hexString, urlEncoded);
and the hmacsha1 function as I'm running on WinRT;
public static byte[] HmacSha1(byte[] key, byte[] data)
{
var crypt = Windows.Security.Cryptography.Core.MacAlgorithmProvider.OpenAlgorithm("HMAC_SHA1");
var keyBuffer = Windows.Security.Cryptography.CryptographicBuffer.CreateFromByteArray(key);
var cryptKey = crypt.CreateKey(keyBuffer);
var dataBuffer = Windows.Security.Cryptography.CryptographicBuffer.CreateFromByteArray(data);
var signBuffer = Windows.Security.Cryptography.Core.CryptographicEngine.Sign(cryptKey, dataBuffer);
byte[] result;
Windows.Security.Cryptography.CryptographicBuffer.CopyToByteArray(signBuffer, out result);
return result;
}
So here's the corresponding outpus;
(JAVA) 92e893efe72a2f7df6ed409ce35819faba191a63:5f1fa09364a6ae7e35a090b434f182652ab8dd76%3A%7B%22expiration%22%3A+1353759442.0991001%2C+%22channel%22%3A+%22dreamhacksc2%22%2C+%22user_agent%22%3A+%22.*
(C#) 63b10e1d8e9f99cd7fba2ed46fe8e4a4a40222f5:5f1fa09364a6ae7e35a090b434f182652ab8dd76%3A%7B%22expiration%22%3A+1353759442.0991001%2C+%22channel%22%3A+%22dreamhacksc2%22%2C+%22user_agent%22%3A+%22.*
as shown above, the ouputs of HMAC_SHA1 from java and c# are not equal. Any ideas? Am I running encoding problems?
Upvotes: 3
Views: 2193
Reputation: 140210
Just keep it simple and the code equal.
Java:
public static String toHexString(byte[] bytes) {
StringBuilder sb = new StringBuilder(bytes.length * 2);
for (int i = 0; i < bytes.length; ++i) {
sb.append(String.format("%02x", bytes[i]));
}
return sb.toString();
}
public static void main(String[] args) {
String str2 = "5f1fa09364a6ae7e35a090b434f182652ab8dd76:{\"expiration\": 1353759442.0991001, \"channel\": \"dreamhacksc2\", \"user_agent\": \".*";
Mac localMac;
try {
localMac = Mac.getInstance("HmacSHA1");
localMac.init(new SecretKeySpec("Wd75Yj9sS26Lmhve"
.getBytes("UTF-8"), localMac.getAlgorithm()));
byte[] result = localMac.doFinal(str2.getBytes("UTF-8"));
String hexString = toHexString(result);
System.out.println(hexString);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
Result:
f52202a4a4e4e86fd42eba7fcd999f8e1d0eb163
C#:
var token = "5f1fa09364a6ae7e35a090b434f182652ab8dd76:{\"expiration\": 1353759442.0991001, \"channel\": \"dreamhacksc2\", \"user_agent\": \".*";
var encoding = new System.Text.UTF8Encoding();
var privateKey = "Wd75Yj9sS26Lmhve";
HMACSHA1 hmac_sha1 = new HMACSHA1(encoding.GetBytes(privateKey));
hmac_sha1.Initialize();
byte[] result = hmac_sha1.ComputeHash(encoding.GetBytes(token));
string hexString = String.Join( "", result.Select( a => a.ToString("x2") ));
Console.WriteLine(hexString);
Result:
f52202a4a4e4e86fd42eba7fcd999f8e1d0eb163
Upvotes: 4
Reputation: 93948
You are confusing bytes with strings. The result of getBytes()
depends on the default character-encoding, which may be different from system to system.
Upvotes: 1
Reputation: 428
Three tips:
When I tested your Java code, I received this value for str3: f52202a4a4e4e86fd42eba7fcd999f8e1d0eb163
That differs from both Java and C# result posted by you. (This online tool also calculates my result.)
Wikipedia contains an example, and it seems to be correct based on Java code and online calculator. In the first step, test your Java and C# code with the "The quick brown fox jumps over the lazy dog", "key", "de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9"
triplet.
It is not a good idea using BigInterger.toString(16) converting byte array to hex string, because when the byte array begins with one ore more zero digit (or hexit?), then the converted hex string will not contains the leading 0 characters.
Upvotes: 4