简体   繁体   English

如何在Java中生成HMAC等效于Python示例?

[英]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. 我正在寻找通过 Java中的Oauth实现一个获得Twitter授权的应用程序。 The first step is getting a request token . 第一步是获取请求令牌 Here is a Python example for app engine. 这是app引擎的Python示例

To test my code, I am running Python and checking output with Java. 为了测试我的代码,我正在运行Python并使用Java检查输出。 Here is an example of Python generating a Hash-Based Message Authentication Code (HMAC): 以下是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 HMAC in 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) {
}

It uses javax.crypto.Mac , all good. 它使用javax.crypto.Mac ,一切都很好。 However, the SecretKey constructors take bytes and an algorithm. 但是, SecretKey构造函数采用字节和算法。

What's the algorithm in the Python example? Python示例中的算法是什么? How can one create a Java secret key without an algorithm? 如何在没有算法的情况下创建Java密钥?

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.BASE64Encoder for a quick implementation here, but you should probably use something that doesn't depend on the Sun JRE. 请注意,我在这里使用sun.misc.BASE64Encoder进行快速实现,但您应该使用不依赖于Sun JRE的东西。 The base64-encoder in Commons Codec would be a better choice, for example. 例如,Commons Codec中的base64编码器将是更好的选择。

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(键,消息),那么默认情况下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. 我之所以提到这个,是因为我遇到了这个确切的问题,并且发现这个答案很有帮助,但是我错过了将摘要方法传递给hmac()的部分,因此走了一个兔子洞。 Hopefully this answer will prevent others doing the same in the future. 希望这个答案可以防止其他人在将来做同样的事情。

eg 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()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM