HMAC SHA1 Signature in Java
Asked Answered
G

2

6

I am trying to interface with a TransUnion web service and I need to provide a HMAC-SHA1 signature to access it.

This example is in the TransUnion documentation:
Input of SampleIntegrationOwner2008‐11‐18T19:14:40.293Z with security key xBy/2CLudnBJOxOtDhDRnsDYq9HTuDVr2uCs3FMzoxXEA/Od9tOuwSC70+mIfpjeG68ZGm/PrxFf/s/CzwxF4Q== creates output of /UhwvT/kY9HxiXaOjpIc/BarBkc=.

Given that data and key, I cannot get this same result in Java. I have tried several online calculators, and none of them return this result either. Is the example in their documentation incorrect, or am I just not handling these strings correctly?

Here is the code I am currently working with:

public static String calcShaHash (String data, String key) {
    String HMAC_SHA1_ALGORITHM = "HmacSHA1";       
    String result = null;

    try {         
        Key signingKey = new SecretKeySpec(key.getBytes(), HMAC_SHA1_ALGORITHM);
        Mac mac = Mac.getInstance(HMAC_SHA1_ALGORITHM);
        mac.init(signingKey);
        byte[] rawHmac = mac.doFinal(data.getBytes());
        result = Base64.encodeBase64String(rawHmac);    
    }
    catch (Exception e) {
        e.printStackTrace(); 
    }       

    return result;
}

Here is my unit test code:

@Test
public void testCalcShaHash() {
    String data = "SampleIntegrationOwner2008-11-18T19:14:40.293Z";
    String key = "xBy/2CLudnBJOxOtDhDRnsDYq9HTuDVr2uCs3FMzoxXEA/Od9tOuwSC70+mIfpjeG68ZGm/PrxFf/s/CzwxF4Q==";
    String result = Utils.calcShaHash(data, key);
    assertEquals(result, "/UhwvT/kY9HxiXaOjpIc/BarBkc=");

}
Gemology answered 2/6, 2012 at 3:17 Comment(2)
A larger excerpt from the documentation might help. One thing I noticed is that the hyphens are not normal hyphens. If you copy and paste them, they are not in the ASCII character set. All I can say for sure is that the hash length appears correct.Lichenology
@John Watts - your comment about the dashes was correct. I copied and pasted the text from a Word document. The dashes were not standard ASCII characters. By putting normal dashes in, the result was correct without needing to decode the key. Please add your comment as an answer.Gemology
L
2

One thing I noticed is that the hyphens are not normal hyphens. If you copy and paste them, they are not in the ASCII character set. All I can say for sure is that the hash length appears correct. The funny thing is, I couldn't get your code to produce the correct answer, even after putting the correct hyphens in. But no matter. It solved the problem. Huzzah!

Lichenology answered 5/6, 2012 at 23:21 Comment(1)
@Gemology Can you copy your updated SSCE from the original question here? I copied your original code, updated it with proper hyphens and it still fails for me. I think there is another difference we still haven't identified that I would like to preserve for posterity.Lichenology
C
3

That looks like a Base64 encoded key. So I think you're going to need to do a base64 decode on it, then pass it to the HMAC. Something like this (just for illustration I haven't tested it, any errors are an exercise for the reader):

public String getHmacMD5(String privateKey, String input) throws Exception{
    String algorithm = "HmacSHA1";
    byte[] keyBytes = Base64.decode(privateKey);
    Key key = new SecretKeySpec(keyBytes, 0, keyBytes.length, algorithm); 
    Mac mac = Mac.getInstance(algorithm);
    mac.init(key); 
    return Base64.encode(mac.doFinal(input.getBytes()));
}
Crucifer answered 2/6, 2012 at 4:31 Comment(3)
I tried that, but still didn't get the correct answer. See code sample above.Gemology
@chubb Is is possible to decrypt the value using the key that is used up for encryption ?Muddler
No HMAC is a one way hash that uses a public/private key pair to validate that the hash was generated using that specific key. In normal one way hash functions (SHA1, MD5, SHA256, etc) there are no secret keys involved so anyone who knows the algorithm can create a hash. HMAC allows you to ensure only the person/system holding a specific key generated this hash and no one else.Crucifer
L
2

One thing I noticed is that the hyphens are not normal hyphens. If you copy and paste them, they are not in the ASCII character set. All I can say for sure is that the hash length appears correct. The funny thing is, I couldn't get your code to produce the correct answer, even after putting the correct hyphens in. But no matter. It solved the problem. Huzzah!

Lichenology answered 5/6, 2012 at 23:21 Comment(1)
@Gemology Can you copy your updated SSCE from the original question here? I copied your original code, updated it with proper hyphens and it still fails for me. I think there is another difference we still haven't identified that I would like to preserve for posterity.Lichenology

© 2022 - 2024 — McMap. All rights reserved.