如何在 Java 中生成与 Python 示例等效的 HMAC?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3208160/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to generate an HMAC in Java equivalent to a Python example?
提问by dfrankow
I'm looking at implementing an app getting Twitter authorization via Oauthin Java. The first step is getting a request token. Here is a Python examplefor app engine.
我正在考虑在 Java中实现一个通过 Oauth获得Twitter 授权的应用程序。第一步是获取请求令牌。这是应用引擎的Python 示例。
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):
为了测试我的代码,我正在运行 Python 并使用 Java 检查输出。以下是 Python 生成基于哈希的消息身份验证代码 (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?
如何在 Java 中复制此示例?
I've seen an example of HMACin 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 SecretKeyconstructors take bytes and an algorithm.
它使用javax.crypto.Mac,一切都很好。但是,SecretKey构造函数采用字节和算法。
What's the algorithm in the Python example? How can one create a Java secret key without an algorithm?
Python 示例中的算法是什么?如何在没有算法的情况下创建 Java 密钥?
采纳答案by Bruno
HmacSHA1 seems to be the algorithm name you need:
HmacSHA1 似乎是您需要的算法名称:
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.BASE64Encoderfor a quick implementation here, but you should probably use something that doesn't depend on the Sun JRE. The base64-encoder in Commons Codecwould be a better choice, for example.
请注意,我在sun.misc.BASE64Encoder这里使用了快速实现,但您可能应该使用不依赖于 Sun JRE 的东西。例如,Commons Codec 中的 base64 编码器将是更好的选择。
回答by markltbaker
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.
一件小事,但如果您正在寻找与 hmac(key,message) 等效的方法,那么默认情况下,python 库将使用 MD5 算法,因此您需要在 Java 中使用 HmacMD5 算法。
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.
我提到这一点是因为我遇到了这个确切的问题,并发现这个答案很有帮助,但是我错过了将摘要方法传递给 hmac() 从而陷入困境的部分。希望这个答案能防止其他人在未来做同样的事情。
e.g. in Python REPL
例如在 Python REPL 中
>>> import hmac
>>> hmac.new("keyValueGoesHere", "secretMessageToHash").hexdigest()
'1a7bb3687962c9e26b2d4c2b833b2bf2'
This is equivalent to the Java method:
这等效于 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);
}
}
Note that in my example I'm doing the equivalent of .hexdigest()
请注意,在我的示例中,我所做的相当于 .hexdigest()

