2012-06-03 79 views
1

所以,我正在使用Java驗證Facebook的signed_request。不幸的是,我一直遇到驗證過程的問題。我看過this documentation,並模仿他們的算法,沒有成功。我也跟着this tutorial,並繼續拿出我的計算簽名不同於Facebook發送的簽名。HMAC SHA-256和Facebook signed_request

或者至少,這是String.equals()告訴我的。

所以我決定再捅一下。

我設置它迭代我的計算簽名和提供的字節。低看,我的簽名的前32個字節完全符合他們的要求。它只是缺少另外400多字節的數據。

當時,我決定我應該更好地理解發生了什麼。我擡頭看了一下SHA-256,發現的確如此,it only creates 32 bytes of information。於是我留下了超過400字節的數據,Facebook聲稱使用HMAC SHA-256算法生成了這些數據。我認爲我應該將SHA-256的最大長度與我正在哈希的數據長度進行比較,但這只是說明有很多空間可供選擇(消息大小:575字節;最大大小:2.305843009213694×10^18字節)。

Facebook是不是在搞鬼?或者我錯過了什麼?

編輯

這是我使用散列數據的功能。我傳入了我的Facebook密碼(用於密鑰)和base64url編碼的JSON對象(用於數據)。它始終返回長度爲32的字節數組,其數據與Facebook提供的簽名的前32個字節匹配。

private byte[] hmacSHA256(String data, String key) throws Exception { 
    SecretKeySpec secretKey = new SecretKeySpec(key.getBytes("UTF-8"), "HmacSHA256"); 
    Mac mac = Mac.getInstance("HmacSHA256"); 
    mac.init(secretKey); 
    mac.update(data.getBytes("UTF-8")); 
    byte[] hmacData = mac.doFinal(); 
    return hmacData; 
} 

回答

6

因爲我也來這裏尋找類似問題的答案。 這是適用於我的代碼:

import org.apache.commons.codec.binary.Base64; 
import javax.crypto.Mac; 
import javax.crypto.spec.SecretKeySpec; 

private JSONObject parseFBSignedRequest(String signedRequest, String secret) throws UnsupportedEncodingException, Exception { 
    //split request into signature and data 
    String[] signedRequests = signedRequest.split("\\.", 2); 
    //parse signature 
    String sig = signedRequests[0]; 

    //parse data and convert to json object 
    String data = signedRequests[1]; 

    //I assumed it is UTF8 
    JSONObject jsonData = new JSONObject(new String(Base64.decodeBase64(data), "UTF-8")); 
    //check signature algorithm 
    if(!jsonData.getString("algorithm").equals("HMAC-SHA256")) { 
     //unknown algorithm is used 
     return null; 
    } 

    //check if data is signed correctly 
    if(!hmacSHA256(signedRequests[1], secret).equals(sig)) { 
     //signature is not correct, possibly the data was tampered with 
     return null; 
    } 
    return jsonData; 
} 

//HmacSHA256 implementation 
private String hmacSHA256(String data, String key) throws Exception { 
    SecretKeySpec secretKey = new SecretKeySpec(key.getBytes("UTF-8"), "HmacSHA256"); 
    Mac mac = Mac.getInstance("HmacSHA256"); 
    mac.init(secretKey); 
    byte[] hmacData = mac.doFinal(data.getBytes("UTF-8")); 
    return new String(Base64.encodeBase64URLSafe(hmacData), "UTF-8"); 
} 
+0

謝謝!我實際上設法弄清楚我的錯在哪裏(我是個白癡,並沒有分配一個字符串的值,我正在做一個操作)。我會給你答案,因爲你提供了代碼。 – Chaosphere2112

+0

謝謝,先生。函數hmacSHA256沒有爲我返回一個正確的值,然後我把你的答案和[在SO上找到的另一個]合併(https://stackoverflow.com/questions/3103652/hash-string-via-sha-256-in -java),並提出了這個返回語句:'返回String.format(「%064x」,新的java.math.BigInteger(1,hmacData));'' – Seza

0

我擡頭SHA-256,並發現,實際上,它只會造成32個字節的信息。於是我留下了超過400字節的數據,Facebook聲稱使用HMAC SHA-256算法生成了這些數據。

簽名的請求的數據是不使用HMAC SHA-256「創造」 - 這是與它簽署

的簽名的請求的第一部分,該點之前,是簽名 - 其餘是數據有效載荷。您必須對有效載荷數據進行散列處理,並將您得到的散列與簽名進行比較 - 這兩者應匹配,以證明簽名的請求是真實的。

如果這不能幫助你看清楚,請給我們一些代碼。

+0

添加了一些代碼,看看那個。我瞭解有效載荷和簽名是不同的。簽名應該是使用應用密鑰作爲密鑰的有效載荷散列。我應該使用不同的方法來散列數據,而不是我上面使用的方法? – Chaosphere2112