You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP使用Base64公证书验签及字节数组适配openssl_verify问题

PHP适配X.509证书验签及字节数组合并数据的解决方案

一、处理Base64格式的公证书

你收到的是Base64编码的DER格式证书,而openssl_verify需要PEM格式的证书作为参数。只需给Base64内容加上PEM标准头尾,并按64字符换行即可:

// 接收的Base64公证书
$base64Cert = "你的Base64证书内容";

// 解码为DER格式二进制
$certDer = base64_decode($base64Cert);
// 转换为PEM格式
$certPem = "-----BEGIN CERTIFICATE-----\n" 
          . chunk_split(base64_encode($certDer), 64, "\n") 
          . "-----END CERTIFICATE-----\n";

// 此时$certPem可直接传入openssl_verify

二、构造正确的待验签字符串

发送方的原始签名数据是前缀UTF8字节数组 + JSON哈希字节数组的合并结果,PHP中字符串本质是字节序列,可直接拼接字节字符串来模拟这个过程:

步骤1:构造前缀字节字符串

按发送方规则拼接前缀,并确保是UTF8编码:

$verb = "POST";
$destination = "https://example.com/webhook";
$signatureDate = "2023-10-12T20:53:50+00:00";
$signaturePrefix = $verb . ";" . $destination . ";" . $signatureDate . ";";

// 转换为UTF8字节序列(PHP字符串直接存储字节)
$prefixBytes = mb_convert_encoding($signaturePrefix, "UTF-8");

步骤2:获取JSON哈希的字节字符串

需要和发送方使用完全相同的哈希算法(比如SHA256),并获取原始字节而非十六进制字符串:

// 原始JSON数据
$jsonData = "你的JSON内容";
// 计算哈希(第三个参数true返回原始字节字符串)
$hashBytes = hash("sha256", $jsonData, true);

步骤3:合并字节字符串得到待验签数据

$data = $prefixBytes . $hashBytes;

三、完整验签代码

注意指定正确的签名算法(需和发送方一致,示例为SHA256withRSA):

// 解码收到的Base64签名
$signature = "接收的Base64签名内容";
$signatureDecoded = base64_decode($signature);

// 执行验签
$ok = openssl_verify($data, $signatureDecoded, $certPem, OPENSSL_ALGO_SHA256);

switch ($ok) {
    case 1:
        echo "签名验证通过";
        break;
    case 0:
        echo "签名验证失败";
        break;
    default:
        echo "验签错误:" . openssl_error_string();
}

常见验签失败排查点

  • 确认哈希算法完全匹配(比如发送方用SHA1还是SHA256)
  • 检查前缀拼接规则是否和发送方一致(包括末尾的分号)
  • 确保JSON数据未被修改(比如空格、换行符是否和发送方一致)
  • 验证证书转换是否正确(可通过openssl_x509_parse($certPem)检查证书信息)

内容的提问来源于stack exchange,提问作者Tym

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 04:49:54