Shopify HMAC 参数验证在 Python 中失败

Dan*_*erz 4 python hmac shopify

我在验证来自 Shopify 的 HMAC 参数时遇到了一些问题。我根据Shopify 文档使用的代码返回了错误的结果。

这是我的注释代码:

import urllib
import hmac
import hashlib

qs = "hmac=96d0a58213b6aa5ca5ef6295023a90694cf21655cf301975978a9aa30e2d3e48&locale=en&protocol=https%3A%2F%2F&shop=myshopname.myshopify.com&timestamp=1520883022"
Run Code Online (Sandbox Code Playgroud)

解析查询字符串

params = urllib.parse.parse_qs(qs)
Run Code Online (Sandbox Code Playgroud)

提取 hmac 值

value = params['hmac'][0]
Run Code Online (Sandbox Code Playgroud)

从每个文档的查询字符串中删除参数

del params['hmac']
del params['signature']
Run Code Online (Sandbox Code Playgroud)

重新组合参数

new_qs = urllib.parse.urlencode(params)
Run Code Online (Sandbox Code Playgroud)

计算摘要

h = hmac.new(SECRET.encode("utf8"), msg=new_qs.encode("utf8"), digestmod=hashlib.sha256)
Run Code Online (Sandbox Code Playgroud)

返回False

hmac.compare_digest(h.hexdigest(), value)
Run Code Online (Sandbox Code Playgroud)

从表面上看,最后一步应该返回 true。此处遵循的每一步都按照 Shopify 文档中的评论进行了概述。

Dan*_*erz 6

我将发布我自己问题的答案,因为在梳理了 Shopify 的论坛和 SO 的其余部分之后,我找不到任何可以明确回答这个问题的内容。

最近,Shopify 开始protocol在查询字符串负载中包含该参数。这本身就不是一个问题,除了一个事实,即Shopify忽略了他们的文档,在提:/不检查签名时将URL编码。这完全是荒谬的,因为他们自己在他们提供的查询字符串中对这些字符进行URL 编码。

因此,要解决此问题,只需提供带有值的safe参数(拟合,对吗?)。完整的工作代码如下所示:urllib.parse.urlencode:/

params = urllib.parse.parse_qsl(qs)
cleaned_params = []
hmac_value = dict(params)['hmac']

# Sort parameters
for (k, v) in sorted(params):
    if k in ['hmac', 'signature']:
        continue

    cleaned_params.append((k, v))

new_qs = urllib.parse.urlencode(cleaned_params, safe=":/")
secret = SECRET.encode("utf8")
h = hmac.new(secret, msg=new_qs.encode("utf8"), digestmod=hashlib.sha256)

# Compare digests
hmac.compare_digest(h.hexdigest(), hmac_value)
Run Code Online (Sandbox Code Playgroud)

希望这对遇到此问题的其他人有所帮助!

请注意,此代码有些简化,因为查询参数不是按字典(按字母顺序)排序的。如果可以更清楚地说明这一点,我也可以更新代码来做到这一点。