Проверка хэша в Webhook

#java #python #security #hash

Вопрос:

Я работаю над настройкой интеграции с сервисом под названием Printify. Я нахожусь в процессе настройки веб-крючков, и у меня есть последний шаг, с которым я сталкиваюсь с трудностями: безопасность с помощью хэш-кодов. Документация по API: https://developers.printify.com/#webhooks — — — > >Защита ваших веб-крючков.

Поток выглядит следующим образом:

  1. Создайте веб-хук через http api и передайте дополнительную подпись x-pfy-заголовка с секретным ключом и вызываемым URL-адресом, который будет прослушиваться моей системой.
  2. При вызове события webhook будет вызван этот вызываемый URL-адрес.
  3. Я должен проверить тело запроса, используя этот секретный ключ, чтобы убедиться, что это законный вызов от Printify.

Шаг 3-это то, где у меня возникают проблемы. Они приводят пример кода на Python:

 import os
import hmac

def sha256hash(request):
    hash = hmac.new(os.environ['SECRET_TOKEN'].encode('utf-8'),
                    request.data.encode('utf-8'), 
                    'sha256')
    return 'sha256='   hash.hexdigest()


def secure_compare(a, b):
    return hmac.compare_digest(a, b)


print('%r' % secure_compare(request.headers['x-pfy-signature'],
                            sha256hash(request)))
 

Похоже, что я создаю некоторую закодированную строку, вводя тело запроса, полученное от Printify, вместе с секретным ключом, а затем проверяю, соответствует ли закодированная строка заголовку запроса x-pfy-подписи, которая будет такой же, как и исходная, которую я передал?

Может ли кто-нибудь проверить, что это правильно, и рассказать, как это сделать с помощью узла?

Ответ №1:

Вот решение NodeJS: https://bytethisstore.com/articles/pg/printify-webhooks-node-js

В документации на самом деле отсутствует шаг. Когда вы создаете секретный ключ, вы должны отправить его в качестве третьего параметра с именем «секрет» при создании веб-крючка. Это та часть, которая отсутствует в документации.

Поэтому, когда вы создаете веб-хук, вы отправляете:

 {
    "topic": "order:created",
    "url": "{webhook_callback_url}",
    "secret": "{secret_key}"
}
 

Затем, когда Printify отправляет данные на вашу конечную точку, они используют этот секретный ключ для хэширования ответа и отправляют этот хэш в качестве заголовка x-pfy-подписи.

Как и в их примере с python, вы должны сравнивать хэши, а не сам секретный ключ. Вам нужно хэшировать данные, отправленные на веб-крючок, с помощью секретного ключа, а затем сравнить свой хэш с отправленной подписью. Все так, как вы описали.

В PHP это намного проще, и именно эту функцию я использую для проверки подписи:

 function validate_webhook($request, $signature): bool
{
    $signature = str_replace('sha256=', '', $signature);
    $hash = hash_hmac('sha256', $request, {secret_key});
    return hash_equals($signature, $hash);
}
 

где $request находится тело запроса и $signature содержимое заголовка x-pfy-подписи.