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

发布于 2024-09-09 01:53:13 字数 2016 浏览 3 评论 0原文

我正在考虑在 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 密钥?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

蓝礼 2024-09-16 01:53:13

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=

请注意,我在这里使用了 sun.misc.BASE64Encoder 进行快速实现,但您可能应该使用不依赖于 Sun 的算法名称JRE。 Commons Codec 中的 base64 编码器例如,将是一个更好的选择。

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.

鼻尖触碰 2024-09-16 01:53:13

这是一件小事,但如果您正在寻找与 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() 的操作

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.

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.

e.g. in Python REPL

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

This is equivalent to the Java method:

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文