如何在Java中生成一个相当于Python示例的HMAC?

2022-08-31 20:12:31

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

为了测试我的代码,我正在运行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]

输出:

$ ./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 构造函数采用字节和算法。

Python示例中的算法是什么?如何在没有算法的情况下创建Java密钥?


答案 1

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

生产:

+3h2gpjf4xcynjCGU5lbdMBwGOc=

请注意,我在这里已经使用了快速实现,但您可能应该使用不依赖于 Sun JRE 的东西。例如,Commons编解码器中的base64编码器将是更好的选择。sun.misc.BASE64Encoder


答案 2

这是一件小事,但如果你正在寻找一个等同于hmac(key,message),那么默认情况下,python库将使用MD5算法,所以你需要在Java中使用HmacMD5算法。

我提到这一点,因为我有这个确切的问题,并找到了这个答案,这很有帮助,但我错过了消化方法被传递到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()的等效操作


推荐