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?
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.