HMAC SHA1 Signature in Java

Shane picture Shane · Jun 2, 2012 · Viewed 17.6k times · Source

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=");

}

Answer

chubbsondubs picture chubbsondubs · Jun 2, 2012

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()));
}