首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 使用 openssl_verify 验证数字签名的完整实例

     編輯:PHP 相關知識

函数功能与签名

以下 VerifyMsg() 函数用于验证数字签名,支持指定摘要算法(默认 SHA1)。

<?php
/**
 * 验证签名
 *
 * @param string $TobeVerified 待验证的签名密文(十六进制字符串)
 * @param string $PlainText    待验证的原文明文
 * @param string $CertFile     签名者公钥证书文件路径
 * @param int    $signature_alg 摘要算法常量,默认 OPENSSL_ALGO_SHA1
 * @return bool 验证成功返回 true,失败返回 false
 */
function VerifyMsg($TobeVerified, $PlainText, $CertFile, $signature_alg = OPENSSL_ALGO_SHA1) {
    // 1. 读取公钥证书
    $fp = fopen($CertFile, "r");
    if (!$fp) {
        // 找不到证书文件
        return false;
    }
    $pub_key = fread($fp, 8192);
    fclose($fp);

    // 2. 获取公钥资源
    $res = openssl_get_publickey($pub_key);
    if (!$res) {
        return false;
    }

    // 3. 验证签名
    // $TobeVerified 为十六进制字符串,需用 pack("H*") 转为二进制
    $signature_bin = pack("H" . strlen($TobeVerified), $TobeVerified);
    $result = openssl_verify($PlainText, $signature_bin, $res, $signature_alg);

    // 4. 释放公钥资源
    openssl_free_key($res);

    // 5. 判断结果:仅 1 表示成功,0 失败,-1 出错
    return (1 === $result);
}
?>

关键点解析

openssl_verify 返回值

  • 1:验证成功,签名有效。
  • 0:验证失败,签名无效或数据被篡改。
  • -1:验证过程出错(如密钥格式错误、算法不支持等)。

仅当返回 1 时才视为验签通过。

算法参数 $signature_alg

  • 默认 OPENSSL_ALGO_SHA1,适用于 RSA 签名。
  • 若使用 DSA 加密,必须设置为 OPENSSL_ALGO_DSS1(即 SHA1 的别名)。
  • 其他可用常量:OPENSSL_ALGO_SHA224、OPENSSL_ALGO_SHA256、OPENSSL_ALGO_SHA384、OPENSSL_ALGO_SHA512、OPENSSL_ALGO_RMD160、OPENSSL_ALGO_MD5 等(需 PHP 版本与 OpenSSL 版本支持)。

签名数据格式处理

函数假设传入的 $TobeVerified 为十六进制字符串(如通过 bin2hex() 得到),因此使用 pack("H" . strlen($TobeVerified), $TobeVerified) 将其还原为二进制签名数据供 openssl_verify 使用。若签名数据已为二进制,可直接传入。

使用示例

<?php
$plain = "Hello, World!";
$cert = "public.pem";
$sig_hex = "3045022100..."; // 来自签名方的十六进制签名

if (VerifyMsg($sig_hex, $plain, $cert)) {
    echo "签名验证通过";
} else {
    echo "签名验证失败: " . openssl_error_string();
}
?>

错误排查建议

  • 确认公钥证书为 PEM 格式,且包含公钥(-----BEGIN PUBLIC KEY-----)。
  • 检查 openssl_error_string() 获取详细错误信息。
  • DSA 密钥务必搭配 OPENSSL_ALGO_DSS1,否则会返回 -1。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved