Как генерировать HMAC в Java, эквивалентном примеру Python?

Я смотрю на реализацию приложения, получающего разрешение Твиттера через OAuth в Java. Первый шаг получает маркер запроса. Вот пример 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?

Я видел пример HMAC в 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) {
}

Это использует javax.crypto. Mac, вся польза. Однако конструкторы SecretKey берут байты и алгоритм.

Каков алгоритм в примере Python? Как можно создать секретный ключ Java без алгоритма?

50
задан Kevin Guan 11 November 2015 в 22:45
поделиться

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.misc.BASE64Encoder для быстрой реализации, но вы, вероятно, должны использовать что-то, что не зависит от Sun JRE. Base64-encoder в Commons Codec был бы лучшим выбором, например.

68
ответ дан 7 November 2019 в 10:56
поделиться
Другие вопросы по тегам:

Похожие вопросы: