2010-07-08 26 views
45

我正在考慮實現一個在Java中獲得Twitter authorization via Oauth的應用程序。第一步是getting a request token。這是適用於應用引擎的Python example如何用Java生成等價於Python示例的HMAC?

爲了測試我的代碼,我運行Python和與Java檢查輸出。這裏是Python生成基於散列的消息認證碼(HMAC)的例子:

​​3210

輸出:

$ ./foo.py 
+3h2gpjf4xcynjCGU5lbdMBwGOc= 

如何一次重複該實施例中在Java中?

我已經看到在Java中example of 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密鑰?

回答

64

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。例如,The base64-encoder in Commons Codec將是更好的選擇。

+0

好一個相當於!謝謝。 – dfrankow 2010-07-09 14:22:09

+0

@Bruno嗨,你能解釋我如何「填零」這裏的密鑰,如果它比推薦框的大小,這是SHA1 TNX – Spring 2012-12-27 00:39:00

+0

160位非常感謝你,很好的例子小。儘管如此,我認爲你一定會用Apache Commons Codec或Guava編碼器改變你的代碼示例;) – Brice 2013-05-02 17:41:06

20

一個小問題,但如果您正在尋找與hmac(鍵,消息)等效的內容,那麼默認情況下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()

+3

encodeHexString在Android上不起作用,所以我不得不使用它:return new String(Hex.encodeHex(rawHmac)); – JustinMorris 2013-08-21 14:52:25

+0

優秀的Python到Java翻譯。有效 ! – 2015-06-26 12:14:46