如何用Java生成等价于Python示例的HMAC?

我正在考虑通过 Java中的Oauth实现一个获得Twitter授权的应用程序。 第一步是获取请求令牌 。 以下是应用程序引擎的Python示例 。

为了testing我的代码,我正在运行Python并使用Java检查输出。 以下是生成基于哈希的消息authentication码(HMAC)的Python示例:

#!/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] 

输出:

 $ ./foo.py +3h2gpjf4xcynjCGU5lbdMBwGOc= 

如何在Java中复制这个例子?

我在Java中看到了一个HMAC的例子 :

 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) { } 

它使用javax.crypto.Mac ,都很好。 但是, SecretKey构造函数需要字节和algorithm。

Python示例中的algorithm是什么? 如何在没有algorithm的情况下创buildJava密钥?

HmacSHA1似乎是您需要的algorithm名称:

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

生产:

 +3h2gpjf4xcynjCGU5lbdMBwGOc= 

请注意,我在这里使用了sun.misc.BASE64Encoder来快速实现,但是您应该使用不依赖于Sun JRE的东西。 例如,Commons Codec中的base64编码器将是一个更好的select。

一个小问题,但是如果你正在寻找一个相当于hmac(键,消息),那么默认情况下python库将使用MD5algorithm,所以你需要在Java中使用HmacMD5algorithm。

我提到这个,因为我有这个确切的问题,发现这个答案是有帮助的,但我错过了一个摘要方法被传入到hmac()的部分,从而下了一个兔子洞。 希望这个答案能够防止其他人在将来做同样的事情。

例如在Python REPL中

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

这相当于Java方法:

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

请注意,在我的例子中,我正在做相当于.hexdigest()

Interesting Posts