首页 > 解决方案 > PHP hash_hmac 到 JS Hmac

问题描述

我正在尝试验证 webhook 签名,我从api2cart的文档中获得了这个 PHP 代码,但我需要在 Javascript 中使用它。我试过但是我无法匹配签名和 HMAC 生成的值,更多详细信息在这里

要遵循的步骤:

  1. 收集所有以“X-Webhook-”开头的标头//我在标头中将其作为 x-webhook- 接收,不知道它是否会影响加密

  2. 从阵列中删除“X-Webhook-Signature”。

  3. 按键按字母顺序对标题进行排序

  4. 将标头编码为 JSON。

  5. 连接字符串,JSON 标头字符串应该放在第一位

  6. 使用 HMAC SHA256 函数对结果字符串进行散列,输出原始二进制数据集为 true (raw_output = true)

使用您的 store_key 作为密钥来生成二进制签名

  1. 用 Base64 编码字符串

$headersForJson = [
'X-Webhook-Error-Code' => '0',
'X-Webhook-Action' => 'update',

'X-Webhook-Timestamp' => '1516291592',

'X-Webhook-Entity' => 'product',

'X-Webhook-Store-Id' => '1',

'X-Webhook-Signature' => 'SGVsbG8gd2l0aCBBUEkyQ2FydA==',

];

$signatureFromRequest = $headersForJson['X-Webhook-Signature'];

unset($headersForJson['X-Webhook-Signature']);

ksort($headersForJson);

$headers = json_encode($headersForJson);

$data = $headers . $params['raw_body'];

$generatedSignature = base64_encode(hash_hmac('sha256', $data, $storeKey, true));

 if (hash_equals($signatureFromRequest, $generatedSignature)) {
   return true;
 }

这是我所做的:

const signature = headers['x-webhook-signature'];
delete headers['x-webhook-signature'];
    // the header contained other keys I had to get keys starting with x-webhooks
    let xkeys = Object.keys(headers).filter(key => key.includes('x-webhook-')).sort();
    let xheaders = JSON.stringify(xkeys.reduce((res, key) => Object.assign(res, { [key]: headers[key] }), {}));
    let data = xheaders + rawBody


const generatedHash = createHmac('SHA256', "SecretKey")
            .update(data, 'utf-8')
            .digest('base64');


return generatedHash === signature

我在这里想念什么?

标签: javascriptphpwebhookshmachmacsha1

解决方案


您需要将标头数组键从例如 x-webhook-entity 转换为 X-Webhook-Entity

例如:

   let xheaders = JSON.stringify(
      xkeys.reduce((res, key) => Object.assign(
        res,
        { [key.split('-').map(s => s[0].toUpperCase() + s.slice(1)).join('-')]: headers[key] }),//format header key from x-webhook-entity to X-Webhook-Entity
        {}
      )
    );

Pipedream 的完整代码:

const crypto = require('crypto');
const storeKey = '5d780e682fbdbd4d04411be86ccd4b30';
const signature = event.headers['x-webhook-signature'];

const headers = event.headers;
delete headers['x-webhook-signature'];

// the header contained other keys I had to get keys starting with x-webhooks
let xkeys = Object.keys(headers).filter(key => key.includes('x-webhook-')).sort();
let xheaders = JSON.stringify(
  xkeys.reduce((res, key) => Object.assign(
    res,
    { [key.split('-').map(s => s[0].toUpperCase() + s.slice(1)).join('-')]: headers[key] }),//format header key from x-webhook-entity to X-Webhook-Entity
    {}
  )
);

const data = xheaders + JSON.stringify(event.body);
const generatedHash = crypto.createHmac('SHA256', storeKey)
            .update(data, 'utf-8')
            .digest('base64');

console.log(signature);
console.log(generatedHash);

let status = 403;

if (signature === generatedHash) {
  status = 200;
}

const response = await $respond({
  status: status,
  immediate: true,
  headers: {},
  body: {"signature":signature, "generatedHash":generatedHash} 
})

return JSON.parse(response.config.data).response

推荐阅读