【发布时间】:2018-04-24 23:47:06
【问题描述】:
我正在尝试使用 python 3.6 验证 facebook signed_requests (https://developers.facebook.com/docs/reference/login/signed-request/) 上的签名。到目前为止,我已经尝试过:
- facebook python sdk 上的 parse_signed_request() 在这里https://facebook-sdk.readthedocs.io
- 这种方法facebook signed request email
- 这也是http://sunilarora.org/parsing-signedrequest-parameter-in-python-bas/
- 使用 python 2.7 和 3.2
-
像这样使用 python 密码库
从 cryptography.hazmat.primitives 导入哈希,hmac 从 cryptography.hazmat.backends 导入 default_backend
h = hmac.HMAC(key, hashes.SHA256(), backend=default_backend()) h.update(消息) 签名 = h.finalize()
通过简单的
replace("-", "+").replace("_", "/")将-_字符替换为+/a la Facebook signed_request Invalid。 我对此抱有希望,但我似乎无法验证一个签名,即使它缺少任何上述符号,例如GlU46mFitdvtOnm56aLR3xQ1RUBzoCY0k2u1kMjBdQA.ey[...]..so.. 是的..我在签名/有效负载上尝试了不同的字符串编码(utf-8 / ascii)
- 不同的哈希算法(sha512 / md5 ..)
- 首先对 base64 字符串进行哈希处理,然后从 base64 解码它们
- 重新生成我的应用密码(我已经仔细检查了有效负载中显示的应用 ID 是否引用了正确的应用,因此是密码)
到目前为止,我无法生成与给定签名请求相同的签名......所以每条 facebook 消息都被认为是无效的(不太理想!)。
Facebook 到底是如何生成这些签名的?如何正确生成它们(或不正确,如果它与 facebook 匹配:P 我不挑剔)以验证它们?
编辑:感谢您的评论。我也读过那个链接..它似乎并没有帮助解决这个问题。这是一步一步的例子 -
> import json
> import base64
> from cryptography.fernet import Fernet
> from cryptography.hazmat.backends import default_backend
> from cryptography.hazmat.primitives import hashes, hmac, padding
> from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
# app secret copied straight from developer.facebook.com -> settings -> basic
> secrect = 'obviouslythisisnttherealone'
# signed_request from facebook
> r = 'xik7puSFmT1d1LNBlqFVTOCb8TiH0Rg1xBfr7zzf9rg.eyJhbGdvcml0aG0iOiJITUFDLVNIQTI1NiIsImNvbW11bml0eV9pZCI6bnVsbCwiaXNzdWVkX2F0IjoxNTI0NTU4NjcxLCJtZXRhZGF0YSI6bnVsbCwicGFnZV9pZCI6MTYxMjU3Njk0NjE4NjAxLCJwc2lkIjoiMTQ2ODkzNzEwNjU2MTA5NSIsInRocmVhZF90eXBlIjoiVVNFUl9UT19QQUdFIiwidGlkIjoiMTQ2ODkzNzEwNjU2MTA5NSJ9'
# spilt on '.'
> b64_sig, b64_data = r.split('.')
> print(b64_sig, b64_data)
xik7puSFmT1d1LNBlqFVTOCb8TiH0Rg1xBfr7zzf9rg eyJhbGdvcml0aG0iOiJITUFDLVNIQTI1NiIsImNvbW11bml0eV9pZCI6bnVsbCwiaXNzdWVkX2F0IjoxNTI0NTU4NjcxLCJtZXRhZGF0YSI6bnVsbCwicGFnZV9pZCI6MTYxMjU3Njk0NjE4NjAxLCJwc2lkIjoiMTQ2ODkzNzEwNjU2MTA5NSIsInRocmVhZF90eXBlIjoiVVNFUl9UT19QQUdFIiwidGlkIjoiMTQ2ODkzNzEwNjU2MTA5NSJ9
# there are no - or _ chars to replace in this so ..
> decoded_data = base64.b64decode(b64_data)
> decoded_sig = base64.b64decode(b64_sig + "=") # add another '=' to pad out the base64 encoding
> print (decoded_data, decoded_sig)
b'{"algorithm":"HMAC-SHA256","community_id":null,"issued_at":1524558671,"metadata":null,"page_id":161257694618601,"psid":"1468937106561095","thread_type":"USER_TO_PAGE","tid":"1468937106561095"}' b'\xc6);\xa6\xe4\x85\x99=]\xd4\xb3A\x96\xa1UL\xe0\x9b\xf18\x87\xd1\x185\xc4\x17\xeb\xef<\xdf\xf6\xb8'
# encode secret into bytes
> bytes_secret = bytes(secret, encoding='ascii')
> h = hmac.HMAC(bytes_secret, hashes.SHA256(), backend=default_backend())
> h.update(decoded_data)
> h.finalize()
b"\xe9\x0f\xbf\xee\xef\xc8\xf0\x96'Im\x1a@\x9d\xc7S\x82%\xe4<\xa0\xbc\xff\x93\xcb\x11~\x7fv\x90\x9f\xb6"
# ^ wrong
# .. uh .. perhaps in the reverse order?
> h = hmac.HMAC(decoded_data, hashes.SHA256(), backend=default_backend())
> h.update(bytes_secret)
> h.finalize()
b'fnc\xceu\xf8\xf7\xda\xc4\xfe\xca\xe2\x1b\x8b\x00\x9en\xbe\xc7a\xf0P\x9a\\\xfd\xaad\xcb[}E='
# ^ wrong
# ok fine, let's try using a different hashing tool
> import binascii
> hex_sig = binascii.hexlify(decoded_sig)
# the sig we want, in hex
> print(hex_sig)
b'c6293ba6e485993d5dd4b34196a1554ce09bf13887d11835c417ebef3cdff6b8'
> from hashlib import sha256
> h = sha256(bytes_secret)
> h.update(decoded_data)
> print(h.hexdigest())
'54acbc303f4d85831e4bb9f4818a233e71e7f7c4eef4a585c61ed70f7cf1e07f'
# ^ wrong
# uh ..
> h = sha256(bytes_secret + decoded_data)
> print(h.hexdigest())
'54acbc303f4d85831e4bb9f4818a233e71e7f7c4eef4a585c61ed70f7cf1e07f'
# ^ wrong
# using 2.0.0 facebook python sdk
> import facebook
> facebook.parse_signed_request(r, secret)
False
这些方法都不起作用(这不是我尝试过的所有方法)..
【问题讨论】: