私は Facebook と協力して、Sun Base64 デコーダーを使用して Java サーブレットで署名付きリクエストを解析しています。署名がほぼ一致しているように見えますが、署名エラーが発生しています。私が理解できないのは、なぜそれが正確に一致しないのかということであり、それは私のコードに問題があるに違いないと信じています。私がやっていることを確認するための最小限のコード:
BASE64Decoder decoder = new BASE64Decoder();
String[] parts = request.getParameter("signed_request").split("\\.", 2);
String signature = new String(decoder.decodeBuffer(parts[0]), "UTF-8");
String rawData = new String(decoder.decodeBuffer(parts[1]), "UTF-8");
if (!isSignedRequestValid(request, obj, signature, parts[1]))
...
private boolean isSignedRequestValid(HttpServletRequest request, JSONObject obj, String signature, String data) throws IOException
{
String expectedSignature = generateSha256Signature(data, FacebookAppSecretKey);
if (!signature.equals(expectedSignature))
{
log("Facebook signatures do not match, expected: " + expectedSignature + ", received: " + signature);
return false;
}
}
private String generateSha256Signature(String data, String key) throws Exception
{
java.net.URLDecoder decoder = new java.net.URLDecoder();
data = decoder.decode(data, "UTF-8"); // mostly here for testing, doesn't seem to make a difference
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(hmacData);
}
私は 2 つの問題に遭遇しました...最初に、予想される署名と提供される署名が 32 対 33 バイトです。しかし、最初の 32 バイトだけを比較すると、等しい場合もありますが、一致しない場合は、正確に 1 ビット一致しません。たとえば、インデックスと値を出力する例は次のとおりです。
index 14 : [15] , [15]
index 15 : [71] , [71]
index 16 : [-10] , [-26] <-- note the different here, which is 16, or one bit
index 17 : [28] , [28]
index 18 : [60] , [60]
私は Facebook のリクエストを解析するのは初めてなので、コードに見落としているものがあると信じなければなりませんが、それを見ていないので、助けが必要なほど長く遊んでいます。そして、オンラインのどこにも答えがありません。ありがとう!