在文档的另一页( X-HUAWEI-CALLBACK-ID
) 上,我发现了类似的描述:
Base64 编码的字符串,已使用回调密钥进行了 HMAC-SHA256 加密。加密前的字符串由时间戳值、nonce 值和回调用户名组成,不带加号。
这里正在描述如何在 Android 上发送消息push.hcm.upstream
。发送上游消息可能是获取有效负载以验证签名的最佳机会。发送时的服务器端过程如下:
Push Kit 服务器接收到上行消息时,会:
- 将接收时间戳、冒号(:)和上行消息组合成一个字符数组进行加密(例如,
123456789:your_data
)。
- 使用 HMAC 签名验证密钥以 HMAC-SHA256 模式加密字符数组,并将加密结果以 Base64 编码生成签名。
X-HW-SIGNATURE
通过 HTTPS 请求标头中的和X-HW-TIMESTAMP
字段
将签名和时间戳信息传输到您的应用服务器。
您的应用服务器需要使用 HTTPS 请求头和 HMAC 签名验证密钥来验证上行消息的有效性。
无论“HMAC 签名验证密钥”是什么;占位符your_data
听起来很相似,就好像(可能尚未进行 base64 编码)$payload->data
将用于生成签名:
/** Concatenate the input string, generate HMAC hash with SHA256 algorithm, then encode as base64. */
private function generate_signature( int $timestamp, string $nonce, string $data_str, string $secret_key): string {
$input = $timestamp.$nonce.$data_str;
$hmac = hash_hmac( 'sha256', $input, $secret_key );
return base64_encode( $hmac );
}
/** Convert the received signature string to object. */
private function to_object( string $signature ): stdClass {
$input = str_getcsv( $signature, '; ' );
$data = new stdClass();
$data->timestamp = (int) str_replace('timestamp=', '', $input[0]);
$data->nonce = (string) str_replace( ' nonce=', '', $input[1]);
$data->value = (string) str_replace( ' value=', '', $input[2]);
return $data;
}
public function hmac_verify( string $raw_body, string $secret_key, string $signature ): bool {
/* Extract data-string from the raw body. */
$payload = json_decode( $raw_body );
$data_str = base64_decode( $payload->data );
/* Convert the received signature string to object. */
$signature = $this->to_object( $signature );
/* Generate a signature which to compare to. */
$generated = $this->generate_signature( $signature->timestamp, $signature->nonce, $data_str, $secret_key);
/* Compare the generated with the received signature. */
return $generated === $signature->value;
}
需要用实际的$_POST
...测试一次
可以从 PushKit控制台获取“HMAC 签名验证密钥”(每个 web-hook) :
