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
在Javascript中验证Facebook签名请求签名_Javascript_Facebook_Sha256_Hmac - Fatal编程技术网

在Javascript中验证Facebook签名请求签名

在Javascript中验证Facebook签名请求签名,javascript,facebook,sha256,hmac,Javascript,Facebook,Sha256,Hmac,我正在用经典ASP构建一个Facebook页面应用程序。我无法匹配Facebook作为发布的signed\u请求的第一部分传递到应用程序中的签名 因为VBScript中很少有用于加密的库,所以我使用服务器端Javascript和来自的crypto js库 我已经尝试将Facebook的文档中的PHP代码示例翻译成Javascript。我可以生成signed\u请求有效负载的HMAC SHA256哈希,但与signed\u请求签名不匹配 我认为问题在于Facebook的签名格式不同。它看起来是二进

我正在用经典ASP构建一个Facebook页面应用程序。我无法匹配Facebook作为发布的
signed\u请求的第一部分传递到应用程序中的签名

因为VBScript中很少有用于加密的库,所以我使用服务器端Javascript和来自的crypto js库

我已经尝试将Facebook的文档中的PHP代码示例翻译成Javascript。我可以生成
signed\u请求
有效负载的HMAC SHA256哈希,但与
signed\u请求
签名不匹配

我认为问题在于Facebook的签名格式不同。它看起来是二进制的(~1.抚Ö…)而我生成的HMAC SHA256哈希是一个十六进制字符串(7f7e8f5f…)。在Facebook的PHP示例中,
hash\uhmac
函数使用原始二进制参数。因此,我认为我需要将Facebook的签名转换为十六进制或将我的签名转换为二进制,以便进行“苹果对苹果”的比较并获得匹配

这是我的密码:

/* Use the libraries from https://code.google.com/archive/p/crypto-js/
crypto-js/crypto-js.min.js
crypto-js/hmac-sha256.min.js
crypto-js/enc-base64.min.js
*/

var signedRequest = Request.queryString("signed_request")

var FB_APP_SECRET = "459f038.....";

var arSR = signedRequest.split(".");
var encodedSig = arSR[0];
var encodedPayload = arSR[1];

var payload = base64UrlDecode(encodedPayload);
var sig = base64UrlDecode(encodedSig);

var expectedSig;

expectedSig = CryptoJS.HmacSHA256(encodedPayload, FB_APP_SECRET); // Unaltered payload string; no match
expectedSig = CryptoJS.HmacSHA256(payload, FB_APP_SECRET); // base64-decoded payload string; no match

if (sig == expectedSig) {
    Response.write(payload);
} else {
    Response.write("Bad signature");
}

function base64UrlDecode(input) {
    // Replace characters and convert from base64.
    return Base64.decode(input.replace("-", "+").replace("_", "/"));
}

在查阅了关于编码的crypto js文档后,我找到了解决方案。crypto js提供的反/编码方法列在的底部的“编码器”下(感谢您的轻推,CBroe)

解决方案是在签名上使用
.toString()
。crypto js似乎使用了阻止比较匹配的word格式。为了坚持使用一个库,我也切换到使用crypto js提供的base64解码

以下是我的更新代码:

/* Use the libraries from https://code.google.com/archive/p/crypto-js/
crypto-js/crypto-js.min.js
crypto-js/hmac-sha256.min.js
crypto-js/enc-base64.min.js
*/

var signedRequest = Request.queryString("signed_request")

var FB_APP_SECRET = "459f038.....";

var arSR = signedRequest.split(".");
var encodedSig = arSR[0];
var encodedPayload = arSR[1];

var payload = base64UrlDecode(encodedPayload);
var sig = base64UrlDecode(encodedSig);

var expectedSig = CryptoJS.HmacSHA256(encodedPayload, FB_APP_SECRET); /******** Correct payload */

if (sig.toString() != expectedSig.toString()) { /******* Use .toString() to convert to normal strings */
    Response.write(payload);
} else {
    Response.write("Bad signature");
}

function base64UrlDecode(input) {
    return CryptoJS.enc.Base64.parse( /******** Decode */
        input.replace("-", "+").replace("_", "/") // Replace characters
    );
}

我最近为他们所需的用户数据删除webhook实现了这个功能。不再需要外部依赖项:

const crypto=require('crypto');
函数parseSignedRequest(signedRequest,secret){
const[signatureReceived,encodedPayload]=signedRequest.split('.',2);
常量有效负载=B64解码(encodedPayload)
const data=JSON.parse(有效负载);
const hmac=crypto.createHmac('sha256',secret).update(有效载荷);
const expectedSignature=hmac.digest('base64');
if(signatureReceived==预期签名){
返回数据;
}否则{
抛出新错误(“签名不匹配”);
}
}
功能B64解码(数据){
const buff=Buffer.from(数据'base64');
返回buff.toString('ascii');
}

这是我的翻译。我也有测试。

根据crypto.js文档,它有自己的base64解码方法-也许可以尝试使用这些方法,而不是
base64.decode
?(完成-+替换后。)