2

私は 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 のリクエストを解析するのは初めてなので、コードに見落としているものがあると信じなければなりませんが、それを見ていないので、助けが必要なほど長く遊んでいます。そして、オンラインのどこにも答えがありません。ありがとう!

4

2 に答える 2