我已在PHP应用程序中成功实施了一个webhook,但我不确定如何验证Sm-Signature
标题。
文档here声明:
我们的webhook回调作为POST请求发送并包含 以下可用于验证请求的请求标头 来自SurveyMonkey:
Sm-Apikey: Your Client ID or API key (if you’re using OLD Authentication) Sm-Signature: # HMAC digest hashed with sha1
我能找到的解释如何完成的唯一documentation是用Python编写的,我根本不熟悉。提供的Python代码是:
import hashlib
import hmac
import base64
def generate_signature(payload, api_key, api_secret):
"""
:type payload: str The response body from the webhook exactly as you received it
:type api_key: str Your API Key for you app (if you have one) otherwise your Client ID
:type api_secret: str Your API Secret for your app
:return: str
"""
# ensure all strings passed in are ascii strings,
# as hmac does not work on unicode
api_key = api_key.encode("ascii")
api_secret = api_secret.encode("ascii")
payload = payload.encode("ascii")
signature = hmac.new(
key='%s&%s' % (api_key, api_secret),
msg=payload,
digestmod=hashlib.sha1)
signature_digest = signature.digest()
return base64.b64encode(signature_digest)
# Compare the signature generated from the request body against the one in the request headers
# Where "request" is the HTTP request received for the event, attributes to access body/headers may vary by framework
hmac.compare_digest(generate_signature(request.body, api_key, api_secret), request.headers['Sm-Signature'])
除了不精通Python之外,我还不熟悉PHP的散列,摘要和其他加密功能。我如何将其解释为PHP和/或解释如何在PHP中执行此验证?
编辑:我很感激努力指出我正确的方向,但我已尝试过该代码,以及其他几个答案的代码,但没有一个产生我需要的结果。此外,我在SurveyMonkey的特定上下文中询问。我没有找到有关SurveyMonkey的v3 webhook验证的PHP实现的文档。这不是重复,因为我的问题具体是如何执行此验证。
到目前为止,我已经尝试了所有这些变体,其中$raw
是未解析的POST邮件正文,$api_sig
是Sm-Signature
标题值,$api_key
是关键作为Sm-Apikey
标题传递,API_CLIENT_ID
是我的客户ID(实际上与Sm-Apikey
相同)。
// Various combinations, each with and without base64 encoding.
hash_hmac('sha1', $raw, $api_key)
base64_encode(hash_hmac('sha1', $raw, $api_key))
hash_hmac('sha1', $raw, $api_sig)
base64_encode(hash_hmac('sha1', $raw, $api_sig))
hash_hmac('sha1', $raw, API_CLIENT_ID)
base64_encode(hash_hmac('sha1', $raw, API_CLIENT_ID))
hash_hmac('sha1', $raw, "$api_key&$api_sig")
base64_encode(hash_hmac('sha1', $raw, "$api_key&$api_sig"))
hash_hmac('sha1', $raw, API_CLIENT_ID."&$api_sig")
base64_encode(hash_hmac('sha1', $raw, API_CLIENT_ID."&$api_sig"))
// This time with raw outputs.
hash_hmac('sha1', $raw, $api_key, TRUE)
base64_encode(hash_hmac('sha1', $raw, $api_key, TRUE))
hash_hmac('sha1', $raw, $api_sig, TRUE)
base64_encode(hash_hmac('sha1', $raw, $api_sig, TRUE))
hash_hmac('sha1', $raw, API_CLIENT_ID, TRUE)
base64_encode(hash_hmac('sha1', $raw, API_CLIENT_ID, TRUE))
hash_hmac('sha1', $raw, "$api_key&$api_sig", TRUE)
base64_encode(hash_hmac('sha1', $raw, "$api_key&$api_sig", TRUE))
hash_hmac('sha1', $raw, API_CLIENT_ID."&$api_sig", TRUE)
base64_encode(hash_hmac('sha1', $raw, API_CLIENT_ID."&$api_sig", TRUE))
这些都没有产生匹配Sm-Signature
的值,并且所有输出都是Sm-Signature
长度的2-3倍。我怀疑需要另一种编码(在HMAC摘要之前和/或之后),但我不知道它会是什么。
编辑2 :感谢Kandalaft将军的示例代码,我找到了解决方案。我没有把握哪些数据作为关键,但他的建议有所帮助。这与我在研究此问题时遇到的信息相结合,使我能够成功执行验证。对于那些寻找这个答案的人来说,它是:
base64_encode(hex2bin(hash_hmac('sha1', $raw, API_CLIENT_ID.'&'.API_SECRET)));
如果管理员可以删除重复的标签,以便我可以将解决方案作为正确答案发布,我将不胜感激。