How to generate an HMAC in Java equivalent to a Python example?
Question: I'm looking at implementing an app getting [Twitter authorization via
Oauth](http://apiwiki.twitter.com/Authentication) in Java. The first step is
[getting a request token](http://apiwiki.twitter.com/Twitter-REST-API-
Method%3A-oauth-request_token). Here is a [Python
example](http://github.com/tav/tweetapp/blob/master/standalone/twitter_oauth_handler.py)
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](http://exampledepot.8waytrips.com/egs/javax.crypto/GenMac.html) 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](http://download.oracle.com/docs/cd/E17409_01/javase/6/docs/api/javax/crypto/Mac.html),
all good. However, the
[SecretKey](http://download.oracle.com/docs/cd/E17409_01/javase/6/docs/api/javax/crypto/SecretKey.html)
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?


Answer: 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](http://commons.apache.org/codec/apidocs/org/apache/commons/codec/binary/Base64.html)
would be a better choice, for example.

