it-swarm.com.de

Wie erstelle ich eine HMAC in Java äquivalent zu einem Python Beispiel?

Ich möchte eine App implementieren, die Twitter-Autorisierung über Oauth in Java erhält. Der erste Schritt ist Abrufen eines Anforderungstokens . Hier ist ein Python-Beispiel für die App-Engine.

Um meinen Code zu testen, führe ich Python und überprüfe die Ausgabe mit Java. Hier ist ein Beispiel für Python Generieren eines Hash-basierten Nachrichtenauthentifizierungscodes (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]

Ausgabe:

$ ./foo.py
+3h2gpjf4xcynjCGU5lbdMBwGOc=

Wie repliziert man dieses Beispiel in Java?

Ich habe ein Beispiel für HMAC in Java gesehen:

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) {
}

Es benutzt javax.crypto.Mac , alles gut. Die Konstruktoren SecretKey benötigen jedoch Bytes und einen Algorithmus.

Wie lautet der Algorithmus im Python Beispiel? Wie kann man einen Java geheimen Schlüssel ohne Algorithmus erstellen?

49
dfrankow

HmacSHA1 scheint der Name des Algorithmus zu sein, den Sie benötigen:

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

produziert:

+3h2gpjf4xcynjCGU5lbdMBwGOc=

Beachten Sie, dass ich hier Sun.misc.BASE64Encoder Für eine schnelle Implementierung verwendet habe, aber Sie sollten wahrscheinlich etwas verwenden, das nicht von der Sun JRE abhängt. Der base64-Encoder in Commons Codec wäre zum Beispiel eine bessere Wahl.

67
Bruno

Eine Kleinigkeit, aber wenn Sie nach einem Äquivalent zu hmac (key, message) suchen, verwendet die Bibliothek python= standardmäßig den MD5-Algorithmus, daher müssen Sie den HmacMD5-Algorithmus in Java verwenden.

Ich erwähne dies, weil ich genau dieses Problem hatte und diese Antwort gefunden habe, die hilfreich war, aber ich habe den Teil verpasst, in dem eine Digest-Methode an hmac () übergeben wurde, und bin so in ein Kaninchenloch gefahren. Hoffentlich verhindert diese Antwort, dass andere in Zukunft dasselbe tun.

z.B. in Python REPL

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

Dies entspricht der Java -Methode:

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

Beachten Sie, dass ich in meinem Beispiel das Äquivalent von .hexdigest () mache.

21
markltbaker