2012-06-02 43 views
3

我想與TransUnion Web服務接口,我需要提供一個HMAC-SHA1簽名來訪問它。在Java中的HMAC SHA1簽名

這個例子是環聯文檔中:
安全輸入的SampleIntegrationOwner2008‐11‐18T19:14:40.293ZxBy/2CLudnBJOxOtDhDRnsDYq9HTuDVr2uCs3FMzoxXEA/Od9tOuwSC70+mIfpjeG68ZGm/PrxFf/s/CzwxF4Q== 創建的/UhwvT/kY9HxiXaOjpIc/BarBkc=輸出。

鑑於數據和密鑰,我無法在Java中獲得相同的結果。我已經嘗試了幾種在線計算器,並且他們都沒有返回這個結果。他們的文檔中的示例是不正確的,還是我沒有正確處理這些字符串?

這裏是我目前正與代碼:

public static String calcShaHash (String data, String key) { 
    String HMAC_SHA1_ALGORITHM = "HmacSHA1";  
    String result = null; 

    try {   
     Key signingKey = new SecretKeySpec(key.getBytes(), HMAC_SHA1_ALGORITHM); 
     Mac mac = Mac.getInstance(HMAC_SHA1_ALGORITHM); 
     mac.init(signingKey); 
     byte[] rawHmac = mac.doFinal(data.getBytes()); 
     result = Base64.encodeBase64String(rawHmac);  
    } 
    catch (Exception e) { 
     e.printStackTrace(); 
    }  

    return result; 
} 

這裏是我的單元測試代碼:

@Test 
public void testCalcShaHash() { 
    String data = "SampleIntegrationOwner2008-11-18T19:14:40.293Z"; 
    String key = "xBy/2CLudnBJOxOtDhDRnsDYq9HTuDVr2uCs3FMzoxXEA/Od9tOuwSC70+mIfpjeG68ZGm/PrxFf/s/CzwxF4Q=="; 
    String result = Utils.calcShaHash(data, key); 
    assertEquals(result, "/UhwvT/kY9HxiXaOjpIc/BarBkc="); 

} 
+1

從文檔的更大的摘錄可能會有所幫助。我注意到的一件事是連字符不是正常的連字符。如果您複製並粘貼它們,它們不在ASCII字符集中。我可以肯定地說哈希長度顯示正確。 –

+0

@John Watts - 你對破折號的評論是正確的。我複製並粘貼來自Word文檔的文本。破折號不是標準的ASCII字符。通過使用正常破折號,結果是正確的,無需解碼密鑰。請添加您的評論作爲答案。 – Shane

回答

2

一件事我注意到的是,連字符是不正常的連字符。如果您複製並粘貼它們,它們不在ASCII字符集中。我可以肯定地說哈希長度顯示正確。有趣的是,即使在輸入正確的連字符後,我也無法讓你的代碼產生正確的答案。但是不管。它解決了這個問題。好哇!

+0

@Shane你可以在這裏複製你最新的SSCE嗎?我複製了你的原始代碼,用適當的連字符更新它,但它仍然失敗。我認爲還有另一個區別,我們還沒有確定我想保留後代。 –

3

這看起來像一個Base64編碼的關鍵。所以我認爲你需要對它做一個base64解碼,然後把它傳遞給HMAC。像這樣的東西(只是爲了說明我沒有測試過,任何錯誤都爲讀者的練習):

public String getHmacMD5(String privateKey, String input) throws Exception{ 
    String algorithm = "HmacSHA1"; 
    byte[] keyBytes = Base64.decode(privateKey); 
    Key key = new SecretKeySpec(keyBytes, 0, keyBytes.length, algorithm); 
    Mac mac = Mac.getInstance(algorithm); 
    mac.init(key); 
    return Base64.encode(mac.doFinal(input.getBytes())); 
} 
+0

我試過了,但還是沒有得到正確的答案。見上面的代碼示例。 – Shane

+0

@chubb是否可以使用用於加密的密鑰來解密值? –

+0

否HMAC是使用公鑰/私鑰對驗證是否使用特定密鑰生成哈希的單向哈希。在常規的單向散列函數(SHA1,MD5,SHA256等)中,沒有涉及任何祕密密鑰,因此知道算法的任何人都可以創建散列。 HMAC允許您確保只有持有特定密鑰的人員/系統纔會生成此散列,而不是其他人。 – chubbsondubs