所以,我正在努力使用Java验证Facebook的signed_request。不幸的是,我一直在遇到验证过程中的问题。我查看了this documentation,并模拟了他们的算法,但没有成功。我也跟着this tutorial,继续提出我的计算签名与Facebook发送的签名不同。
或者至少,这就是String.equals()告诉我的。
所以我决定再捅一下。
我将其设置为迭代计算签名中的字节和提供的字节。低,看,我的签名的前32个字节完全匹配他们。它只丢失了另外400多字节的数据。
那时,我觉得我应该更好地了解到底发生了什么。我查了一下SHA-256,发现确实是it only creates 32 bytes of information。那么我留下了超过400字节的数据,Facebook声称是使用HMAC SHA-256算法生成的。我想我应该将SHA-256的最大长度与我正在散列的数据的长度进行比较,但这只是表明有方法,方式,方式有很多空间(消息大小:575字节;最大大小:2.305843009213694 x 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;
}
答案 0 :(得分: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");
}
答案 1 :(得分:0)
我查了一下SHA-256,发现确实只创建了32个字节的信息。所以我留下了超过400字节的数据,Facebook声称是使用HMAC SHA-256算法生成的。
签名请求的数据不是使用HMAC SHA-256 “created” - 它与签名。
签名请求的第一部分在点之前是签名 - 其余部分是数据 payload 。您必须对有效负载数据进行哈希处理,并将获得的哈希值与签名进行比较 - 这两者应该匹配,以证明签名请求是真实的。
如果这对您没有帮助,请告诉我们一些代码。