Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to generate an HMAC in Java equivalent to a Python example?

I'm looking at implementing an app getting Twitter authorization via Oauth in Java. The first step is getting a request token. Here is a Python example for app engine.

To test my code, I am running Python and checking output with Java. Here is an example of Python generating a Hash-Based Message Authentication Code (HMAC):

#!/usr/bin/python  from hashlib import sha1 from hmac import new as hmac  key = "qnscAdgRlkIhAUPY44oiexBKtQbGY0orf7OV1I50" message = "foo"  print "%s" % hmac(key, message, sha1).digest().encode('base64')[:-1] 

Output:

$ ./foo.py +3h2gpjf4xcynjCGU5lbdMBwGOc= 

How does one replicate this example in Java?

I've seen an example of HMAC in Java:

try {     // Generate a key for the HMAC-MD5 keyed-hashing algorithm; see RFC 2104     // In practice, you would save this key.     KeyGenerator keyGen = KeyGenerator.getInstance("HmacMD5");     SecretKey key = keyGen.generateKey();      // Create a MAC object using HMAC-MD5 and initialize with key     Mac mac = Mac.getInstance(key.getAlgorithm());     mac.init(key);      String str = "This message will be digested";      // Encode the string into bytes using utf-8 and digest it     byte[] utf8 = str.getBytes("UTF8");     byte[] digest = mac.doFinal(utf8);      // If desired, convert the digest into a string     String digestB64 = new sun.misc.BASE64Encoder().encode(digest); } catch (InvalidKeyException e) { } catch (NoSuchAlgorithmException e) { } catch (UnsupportedEncodingException e) { } 

It uses javax.crypto.Mac, all good. However, the SecretKey constructors take bytes and an algorithm.

What's the algorithm in the Python example? How can one create a Java secret key without an algorithm?

like image 754
dfrankow Avatar asked Jul 08 '10 21:07

dfrankow


People also ask

How do I use HMAC authentication in Java?

Java provides a built-in Mac class for HMAC generating.After initializing the Mac object, we call the doFinal() method to perform the HMAC operation. This method returns a byte array containing the HMAC result. In this test, we're using the HmacSHA512 algorithm with simple string data and keys.

How do I create a HMAC?

First, enter the plain-text and the cryptographic key to generate the code. Then, you can use select the hash function you want to apply for hashing. The default is SHA-256. Then you can submit your request by clicking on the compute hash button to generate the HMAC authentication code for you.

Is HMAC included in Python?

This is a stand alone packaging of the hashlib compatible hmac library included with Python 2.5 so that it can be used together with the hashlib backport on older versions of Python (tested on 2.4).

How do I use HMAC in Python?

We first create an instance of HMAC using new() method by giving it key and message as bytes and hashing algorithm name as sha1. We are then printing message authentication code. Our second part of the code creates the HMAC instance without any initial message. It then uses update() method to add message.


2 Answers

HmacSHA1 seems to be the algorithm name you need:

SecretKeySpec keySpec = new SecretKeySpec(         "qnscAdgRlkIhAUPY44oiexBKtQbGY0orf7OV1I50".getBytes(),         "HmacSHA1");  Mac mac = Mac.getInstance("HmacSHA1"); mac.init(keySpec); byte[] result = mac.doFinal("foo".getBytes());  BASE64Encoder encoder = new BASE64Encoder(); System.out.println(encoder.encode(result)); 

produces:

+3h2gpjf4xcynjCGU5lbdMBwGOc= 

Note that I've used sun.misc.BASE64Encoder for a quick implementation here, but you should probably use something that doesn't depend on the Sun JRE. The base64-encoder in Commons Codec would be a better choice, for example.

like image 58
Bruno Avatar answered Sep 21 '22 06:09

Bruno


A minor thing but if you are looking for an equivalent to hmac(key,message) then by default the python library will use the MD5 algorithm, so you need to use the HmacMD5 algorithm in Java.

I mention this because I had this exact problem and found this answer which was helpful, but I missed the part where a digest method was passed in to hmac() and thus went down a rabbit hole. Hopefully this answer will prevent others doing the same in the future.

e.g. in Python REPL

>>> import hmac >>> hmac.new("keyValueGoesHere", "secretMessageToHash").hexdigest() '1a7bb3687962c9e26b2d4c2b833b2bf2' 

This is equivalent to the Java method:

import org.apache.commons.codec.binary.Hex; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec;  public class HashingUtility {     public static String HMAC_MD5_encode(String key, String message) throws Exception {          SecretKeySpec keySpec = new SecretKeySpec(                 key.getBytes(),                 "HmacMD5");          Mac mac = Mac.getInstance("HmacMD5");         mac.init(keySpec);         byte[] rawHmac = mac.doFinal(message.getBytes());          return Hex.encodeHexString(rawHmac);     } } 

Note that in my example I'm doing the equivalent of .hexdigest()

like image 38
markltbaker Avatar answered Sep 18 '22 06:09

markltbaker