Facebook即时玩家签名验证失败

时间:2019-03-11 09:37:53

标签: php facebook encryption facebook-instant-games

我目前正在Facebook上开发即时游戏,需要验证玩家信息是否来自Facebook。 Facebook通过哈希签名提供验证,如下所示:

https://developers.facebook.com/docs/games/instant-games/sdk/fbinstant6.2#signedplayerinfo

我遵循了概述的步骤,但是无法获得匹配的签名:

这是签名:

$_POST['psig'] = 'je3yV8uKmysDrjXv1xp_RY2rTMJLEREM7xj8SGt5HEk.eyJhbGdvcml0aG0iOiJITUFDLVNIQTI1NiIsImlzc3VlZF9hdCI6MTU1MjI1NTc2OCwicGxheWVyX2lkIjoiMjA1OTE4OTA2MDgyMzk4MyIsInJlcXVlc3RfcGF5bG9hZCI6InBkYXRhIn0';

1)将签名分成两部分,以“。”分隔。字符。

$first_part = explode('.', $_POST['psig'])[0];
echo $first_part;

// Output:
je3yV8uKmysDrjXv1xp_RY2rTMJLEREM7xj8SGt5HEk

$second_part = explode('.', $_POST['psig'])[1];
echo $second_part;

// Output
eyJhbGdvcml0aG0iOiJITUFDLVNIQTI1NiIsImlzc3VlZF9hdCI6MTU1MjI1NTc2OCwicGxheWVyX2lkIjoiMjA1OTE4OTA2MDgyMzk4MyIsInJlcXVlc3RfcGF5bG9hZCI6InBkYXRhIn0

2)使用base64url编码对第一部分(编码签名)进行解码。

echo base64_decode($first_part);

// Output:
���Wˊ�+�5��Qcj�0��DC;�?�G

3)使用base64url编码对第二部分(响应有效负载)进行解码,该部分应该是具有以下字段的JSON对象的字符串表示形式:**算法-始终等于HMAC-SHA256 ** issue_at-Unix发出此响应的时间戳。 ** player_id-玩家的唯一标识符。 ** request_payload-调用FBInstant.player.getSignedPlayerInfoAsync时指定的requestPayload字符串。

$payload = base64_decode($second_part);
echo $payload;

// Output:
{"algorithm":"HMAC-SHA256","issued_at":1552255768,"player_id":"2059189060823983","request_payload":"pdata"}

4)使用HMAC SHA-256和您的应用程序秘密将整个响应有效负载字符串散列,并确认它与编码签名相同。

$check = hash_hmac('sha256', $payload, 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', true);
echo $check;

// Output:
n4Q�Kމ`<�?�����tT�~x����L�

我已经花了几个小时,无法弄清楚我在做什么错!

1 个答案:

答案 0 :(得分:3)

最后知道了!

我有2个错误:

1)在解码编码签名以进行检查时,应使用base64decode URL,而不是常规的base64decode。因此,第2步中的代码应如下所示:

$first_part = base64_decode(str_replace(array('-', '_'), array('+', '/'), $first_part));

2)生成的散列应具有原始编码的response payload字符串,而不是已解码的字符串。该文件对此不是很清楚。所以应该像这样:

$check = hash_hmac('sha256', $second_part, $app_secret, true);

通过上述操作,解码后的签名将等于生成的哈希中的二进制数据:)

最后检查签名是否有效: if($first_part == $check){ //valid }