php - 将 PHP POST 响应的 JSON 主体编码为 HMAC SHA256,然后编码为 Base64

标签 php json post base64 webhooks

如何从 HTTP POST webhook 接收原始 JSON 响应?


我正在使用 API 并验证对 webhook 的 POST 确实来自相应的公司 API,他们建议使用此方法:

To allow a client to verify a webhook message has in fact come from SIGNIFYD, an X-SIGNIFYD-SEC-HMAC-SHA256 header is included in each webhook POST message. The contents of this header is the Base64 encoded output of the HMAC SHA256 encoding of the JSON body of the message, using the team's API key as the encryption key. To verify the authenticity of the webhook message, you should calculate this value yourself and verify it equals the value contained in the header.

对于测试环境,“ secret ” key 是 ABCDE 而不是“团队 API key ”。

我像这样用 PHP 接收它:

<?php

// Get relevant Signifyd custom headers to be used for verification
$header_sig_topic = $_SERVER['HTTP_X_SIGNIFYD_TOPIC'];
$header_sig_sec_hmac = $_SERVER['HTTP_X_SIGNIFYD_SEC_HMAC_SHA256'];

// Get POST body
$webhookContent = "";
$webhook = fopen('php://input' , 'r');
while (!feof($webhook)) {
    $webhookContent .= fread($webhook, 4096);
}
fclose($webhook);

?>

然后我像这样将它处理成散列:

<?php
$sig_ver_sha = hash_hmac('sha256', $webhookContent, $secret);
$sig_ver_hash = base64_encode( $sig_ver_sha );
?>

但是,我哪里出错了,因为我计算的散列是

OTc1YzExZDY2ZTE1MTVmYmJmNWNhNDRhNWMxZGIzZDk0NmM3OGE4NDU2N2JkYTJmZDJlYWI0ODRhNjlhNTdiYg==

虽然相同样本响应 header 的 header 始终带有

W+D70ded8u5DG7P4BcG0u2etvAqQZvxz70Q4OXh0vlY=

我以为我弄错了 JSOn 正文,所以我尝试了 json_encode 和 json_decode 的所有组合,但没有任何帮助,我的哈希值永远不匹配。

我也尝试过使用 $webhookContent = json_decode(file_get_contents('php://input'), true); 来存储 POST 正文,但结果是空的($_POST 没有' 工作)。

除了接收 JSON,我是否还做错了什么?


作为测试响应正文的 JSON 始终带有 W+D70ded8u5DG7P4BcG0u2etvAqQZvxz70Q4OXh0vlY= 作为用于验证的哈希键:

{ "analysisUrl": "https://signifyd.com/v2/cases/1/analysis", "entriesUrl": "https://signifyd.com/v2/cases/1/entries", "notesUrl": "https://signifyd.com/v2/cases/1/notes", "orderUrl": "https://signifyd.com/v2/cases/1/order", "guaranteeEligible":false, "status":"DISMISSED", "uuid":"709b9107-eda0-4cdd-bdac-a82f51a8a3f3", "headline":"John Smith", "reviewDisposition":null, "associatedTeam":{ "teamName":"anyTeam", "teamId":26, "getAutoDismiss":true, "getTeamDismissalDays":2 }, "orderId":"19418", "orderDate":"2013-06-17T06:20:47-0700", "orderAmount":365.99, "createdAt":"2013-11-05T14:23:26-0800", "updatedAt":"2013-11-05T14:23:26-0800", "adjustedScore":262.6666666666667, "investigationId":1, "score":262.6666666666667, "caseId":1, "guaranteeDisposition":"APPROVED"}

如果有助于了解我哪里出错了,提供了一个示例,但它是用 Python 编写的:

Mac sha256HMAC = javax.crypto.Mac.getInstance("HmacSHA256");
SecretKeySpec secretKey = new SecretKeySpec(teamAPIKEY.getBytes(), "HmacSHA256");
sha256HMAC.init(secretKey);
String encodedHMAC256 = Base64.encodeBase64String(sha256HMAC.doFinal(jsonBody.getBytes("UTF-8")));

最佳答案

我的错误在于没有将 $raw_output parameter of the hash_hmac() function 指定为 true

raw_output
When set to TRUE, outputs raw binary data. FALSE outputs lowercase hexits.

因此,由于我没有将 $raw_output 指定为 true,所以我得到的是 hexits 而不是原始二进制输出,看起来像这个:975c11d66e1515fbbf5ca44a5c1db3d946c78a84567bda2fd2eab484a69a57bb

编辑:这里的答案是

<?php
$sig_ver_sha = hash_hmac('sha256', $webhookContent, $secret, true);
$sig_ver_hash = base64_encode( $sig_ver_sha );
?>

关于php - 将 PHP POST 响应的 JSON 主体编码为 HMAC SHA256,然后编码为 Base64,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38092371/

相关文章:

laravel - 使用 Vagrant 执行 POST 请求时连接被拒绝

wordpress - 视觉 Composer 发布过去事件的网格自定义查询字符串

php - 如何更改单元测试的应用程序 URL?

php - 尝试使用 php ( HTTP POST ) 从 iOS 连接到 MySQL 数据库

javascript - Knockoutjs 嵌套的 observableArrays

android - 将 DateTime 对象 java 转换为 Json 字符串

php函数和mysql插入

php - 重构 ZF Controller 文件?

c++ - 将 json-Container 复制分配给 vector

python - 如何在 python 中获取 POST/GET 数据