我尝试使用python 3.6验证facebook signed_requests(https://developers.facebook.com/docs/reference/login/signed-request/)上的签名。到目前为止,我已经尝试过:
使用像这样的python加密库
来自cryptography.hazmat.primitives的导入哈希,hmac 来自cryptography.hazmat.backends import default_backend
h = hmac.HMAC(key,hashes.SHA256(),backend = default_backend()) h.update(消息) signature = h.finalize()
通过简单的-_
将+/
字符替换为replace("-", "+").replace("_", "/")
la Facebook signed_request Invalid。
我对这个有希望,但我似乎无法验证一个信号,即使它缺少上述任何一个符号,例如GlU46mFitdvtOnm56aLR3xQ1RUBzoCY0k2u1kMjBdQA.ey[...]
..所以..是啊..
我在签名/有效负载上尝试了不同的字符串编码(utf-8 / ascii)
到目前为止,我已经无法生成给定签名请求的相同签名..所以每条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
这些方法都不起作用(这不是我尝试过的所有内容)..
答案 0 :(得分:0)
更新:希望这证明有助于其他人寻找类似的东西 - 签名生成功能是正确的,在某些前端代码中隐藏的(错误的)应用程序ID的硬编码中存在一个错误。