各位开发者好,

我遇到了加载回调(以及扩展卸载回调)的问题。
我正在尝试按照文档中描述的算法验证请求的真实性。 https://developer.bigcommerce.com/apps/load#signed-payload

我能够解码 json 字符串并且数据正确,但签名永远不匹配。我确保使用正确的客户端 key ,并尝试了不同的编码/解码方案,但没有成功。

另一个问题是他们在示例中(以及在他们的 sample app 中)提供的代码片段(PHP)。当签名匹配时,它们似乎返回 null,而当它们不匹配时,它们似乎返回了解码数据……( try secureCompare() )
这意味着每次都会通过安全测试,因为在我所有的尝试中,签名都不匹配。

我在这里错过了什么吗?

编辑:这是文档中的示例。我真的不能给你样本数据,因为客户的 secret 是保密的......

function verify($signedRequest, $clientSecret)
{
    list($payload, $encodedSignature) = explode('.', $signedRequest, 2);

    // decode the data
    $signature = base64_decode($encodedSignature);
    $data = json_decode(base64_decode($payload), true);

    // confirm the signature
    $expectedSignature = hash_hmac('sha256', $payload, $clientSecret, $raw = true);

    if (secureCompare($signature, $expectedSignature)) {
        error_log('Bad Signed JSON signature!');
        return null;
    }

    return $data;
}

function secureCompare($str1, $str2)
{
    $res = $str1 ^ $str2;
    $ret = strlen($str1) ^ strlen($str2); //not the same length, then fail ($ret != 0)
    for($i = strlen($res) - 1; $i >= 0; $i--) {
        $ret += ord($res[$i]);
    }
    return !$ret;
}

最佳答案

您没有遗漏任何东西,也不是时钟同步问题 - herehere 提供的 28 行示例代码有一些非常严重的缺陷:

  • 示例代码执行原始 base64- 编码的 JSON 的 hash_hmac,而不是 base64 解码的 JSON。 (BigCommerce API 提供给您的哈希实际上是 base64- 解码的 JSON 的哈希)。
  • 由于 hash_hmac 是用 $raw=true 调用的,这意味着两个字符串总是有很大的不同:一个是原始二进制,另一个是十六进制。
  • secureCompare 逻辑检查错误。 if (secureCompare... 函数的 verify 部分期望与 secureCompare 函数相反的行为。如果在字符串匹配时 secureCompare 函数返回 true,我们为什么要调用 error_log

  • 把所有这三个问题放在一起,你最终得到的代码看起来可以工作,但实际上却默默地失败了。如果您使用示例代码,您可能会允许您的应用程序处理任何和所有“签名”请求!

    这是我更正的 verify 函数实现:
    <?php
    
    function verifySignedRequest($signedRequest, $clientSecret)
    {
        list($encodedData, $encodedSignature) = explode('.', $signedRequest, 2);
    
        // decode the data
        $signature = base64_decode($encodedSignature);
        $jsonStr = base64_decode($encodedData);
        $data = json_decode($jsonStr, true);
    
        // confirm the signature
        $expectedSignature = hash_hmac('sha256', $jsonStr, $clientSecret, $raw = false);
        if (!hash_equals($expectedSignature, $signature)) {
            error_log('Bad signed request from BigCommerce!');
            return null;
        }
        return $data;
    }
    

    10-08 06:54