Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/facebook/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Facebook签名请求解码哈希似乎不完全匹配_Java_Facebook - Fatal编程技术网

Java Facebook签名请求解码哈希似乎不完全匹配

Java Facebook签名请求解码哈希似乎不完全匹配,java,facebook,Java,Facebook,我正在使用Facebook,并使用Sun Base64解码器在Java servlet中解析已签名的请求。我收到签名失败,尽管签名看起来几乎匹配。我不明白的是为什么它不完全匹配,我相信这一定是我的代码有问题。查看我正在做什么的最低代码: BASE64Decoder decoder = new BASE64Decoder(); String[] parts = request.getParameter("signed_request").split("\\.", 2); String signat

我正在使用Facebook,并使用Sun Base64解码器在Java servlet中解析已签名的请求。我收到签名失败,尽管签名看起来几乎匹配。我不明白的是为什么它不完全匹配,我相信这一定是我的代码有问题。查看我正在做什么的最低代码:

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);
    }
我遇到两个问题。。。首先,预期的vs.提供的签名是32字节vs.33字节。但是如果我只比较前32个字节,有时它们是相等的,但是当它不匹配时,它就不匹配一位。例如,打印出索引和值一个示例是:

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]
索引14:[15],[15]
索引15:[71],[71]

索引16:[-10],-26]似乎有两个问题。。。首先,提供的Facebook签名的解码将解码为33字节,而不是32字节。所以我只使用前32个字节(不关心最后一个字节是什么…我猜只是一个填充函数)

另一个问题是+到-的URL编码。在Base64解码之前使用URLDecoder解码Facebook签名并没有解决问题。相反,我这样做了:

    BASE64Decoder decoder = new BASE64Decoder();
    String[] parts = request.getParameter("signed_request").split("\\.", 2);
    String rawSig = parts[0];
    rawSig = rawSig.replaceAll("\\-", "\\+");
    byte[] signature = decoder.decodeBuffer(rawSig);

这就足够了,前32位现在总是匹配计算出的签名。我觉得奇怪的是,URL编码是以这样一种方式完成的,以至于URLDecover.decode()没有修复它。如果有人知道这个原因,你肯定会感到好奇。

显然,你也必须将
\uu
分为
/

发现一件事:

存在URL变体的已修改Base64,其中标准Base64的“+”和“/”字符分别替换为“-”和“\”


您不能将任意字节(如SHA哈希)解析为UTF8。我不认为是这样。通过使用decoder.decodeBuffer(),我将其更改为所有字节数组,返回字节数组,并将其与作为字节数组的hmacData进行比较。结果发现它们有不同的长度,32和33。我从generate signature方法生成的是32字节。我从facebook得到的签名请求是33字节。这让我怀疑解码器函数是否有错误。而且,这似乎取决于数据。如果我多次运行它,有时比较正确(比较前32个字节),有时则不正确。所以数据中有些东西似乎很重要。我想知道它是否与空间到+转换有关?