首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从hash_hmac到hash_hmac

从hash_hmac到hash_hmac
EN

Stack Overflow用户
提问于 2021-06-11 18:15:50
回答 2查看 439关注 0票数 2

我试图验证一个web钩子签名,我有来自api2cart文档的这个PHP代码,但是我需要它在Javascript.I中,我尝试了,但是我无法匹配签名和HMAC生成的值,更详细的这里

应采取以下步骤:

  1. 收集所有以“X-Web钩子-”//我作为x-web钩子接收到的标题-在我的标题中,不知道它是否影响加密。
  2. 从数组中删除“X-Web钩子签名”。
  3. 按键按字母顺序排序标头
  4. 将头编码为JSON。
  5. 连接字符串,JSON头字符串应该放在第一位
  6. 使用HMAC SHA256函数哈希结果字符串,并输出原始二进制数据集true (raw_output = true)

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

  1. 在Base64中编码字符串
代码语言:javascript
复制
$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;
 }

以下是我所做的:

代码语言:javascript
复制
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

我在这里错过了什么?

EN

回答 2

Stack Overflow用户

发布于 2021-10-28 07:28:30

您需要将头数组键从x-web钩子实体转换为X-web钩子实体。

例如:

代码语言:javascript
复制
   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
        {}
      )
    );

使用Pipe梦的完整代码:

代码语言:javascript
复制
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
票数 0
EN

Stack Overflow用户

发布于 2021-10-29 11:27:01

我也有同样的问题,我用:

  1. 标题必须以大写字母表示。
  2. 主体必须是JSON.stringify ( req.body ),req.body必须是JSON对象,而不是文本(不是raw_body)

这对我来说很管用:

代码语言:javascript
复制
const validateRequest = (headers, body, storeKey) => {
  const webhookHeaders = {
    "X-Webhook-Action": headers["x-webhook-action"],
    "X-Webhook-Entity": headers["x-webhook-entity"],
    "X-Webhook-Error-Code": headers["x-webhook-error-code"],
    "X-Webhook-Store-Id": headers["x-webhook-store-id"],
    "X-Webhook-Timestamp": headers["x-webhook-timestamp"]
  };

  const signatureFromRequest = headers["x-webhook-signature"];
  const data = JSON.stringify(webhookHeaders) + JSON.stringify(body);
  const generatedSignature = crypto
    .createHmac("sha256", storeKey)
    .update(data)
    .digest("base64");

  return !!crypto.timingSafeEqual(
    Buffer.from(signatureFromRequest),
    Buffer.from(generatedSignature)
  );
};

你可以这样称呼它:

代码语言:javascript
复制
const headers = {
  "x-webhook-entity": "product",
  "x-webhook-action": "update",
  "x-webhook-store-id": "0",
  "x-webhook-error-code": "0",
  "x-webhook-timestamp": "1635502511",
  "x-webhook-signature": "Ua1dtsDBi+37fEGr3mTHN7laZqLQpl+tEK02RDAg++0="
};
const body = { id: "28" };
const storeKey = "ed58a22dfecb405a50ea3ea56979360d";
const isValid = validateRequest(headers, body, storeKey);

console.log(isValid ? "success" : "failed"); // success
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67941788

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档