Reputation: 79
I have this Powershell snippet, which I cannot change and provides the Hash I need to match:
$key = 'test'
$bytes = [Text.Encoding]::UTF8.GetBytes($key)
WRITE-HOST "bytes: " $bytes
$hmacsha = new-object system.security.cryptography.HMACSHA1
$hmacsha.key = $bytes
$hash = $hmacsha.ComputeHash($bytes)
WRITE-HOST "hash: " $hash
Which gives this result:
bytes: 116 101 115 116
hash: 12 148 81 92 21 229 9 91 138 135 165 11 160 223 59 243 142 208 95 230
And this in Java:
String key = "test";
byte[] bytes = key.getBytes("UTF-8");
System.out.println("bytes: " + Arrays.toString(bytes));
MessageDigest md = MessageDigest.getInstance("SHA-1");
byte[] keyBytes = md.digest(bytes);
SecretKey sk = new SecretKeySpec(keyBytes, "HmacSHA1");
Mac mac = Mac.getInstance("HmacSHA1");
mac.init(sk);
byte[] hash = mac.doFinal(keyBytes);
System.out.println("hash 1: " + Arrays.toString(hash));
sk = new SecretKeySpec(bytes, "HmacSHA1");
mac = Mac.getInstance("HmacSHA1");
mac.init(sk);
hash = mac.doFinal(bytes);
System.out.println("hash 2: " + Arrays.toString(hash));
Which outputs:
bytes: [116, 101, 115, 116]
hash 1: [-112, -37, 64, 65, -91, -97, 36, 60, -80, -110, 62, -105, -63, -69, -79, -18, 29, -95, 23, -116]
hash 2: [12, -108, 81, 92, 21, -27, 9, 91, -118, -121, -91, 11, -96, -33, 59, -13, -114, -48, 95, -26]
I cannot seem to get the Hash to match what Powershell is outputting. In both examples I am creating a hmacsha1 instance with a key of "test", then getting the hash of "test", but both have some minor difference causing them to give different results.
Upvotes: 0
Views: 270
Reputation: 6860
You are not getting 2 different hashes. Matter of fact ...
12, -108, 81, 92, 21, -27, 9, 91, -118, -121, -91, 11, -96, -33, 59, -13, -114, -48, 95, -26
is the same as
12 148 81 92 21 229 9 91 138 135 165 11 160 223 59 243 142 208 95 230
What is happening is in java when you turn to string it is making these values signed.
An example of this is with -108 and 148
00000000,10010100 = 148
11111111,10010100 = -108
If you want to make the byte look unsigned you can use 0xFF combined with the byte.
byte b = (byte) Integer.parseInt("148");
System.out.println(b);
outputs : -108
byte b = (byte) Integer.parseInt("148");
System.out.println(b & 0xFF);
outputs : 148
What is happening is you are usinga bitwise AND operator so 0xFF = 255 aka 11111111 and matching common bits and keeping them.
00000000,11111111 = 255 aka 0xFF
11111111,10010100 = -108
--------
00000000,10010100 = 148
Upvotes: 1