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

PHP 利用 OpenSSL 生成数字签名的实战代码详解

     編輯:PHP 相關知識

核心功能:从 PFX 证书生成签名

以下 sign() 函数演示如何读取 PFX(PKCS#12)格式证书文件,提取私钥并对数据进行签名,最后返回十六进制签名字符串。

<?php
/**
 * 根据原文生成签名内容
 *
 * @param string $strData 原文内容
 * @return string|bool 成功返回十六进制签名字符串,失败返回 false/空字符串/'0'
 */
function sign($strData) {
    $filePath = 'test.pfx'; // PFX 证书路径
    if (!file_exists($filePath)) {
        return false;
    }

    $pkcs12 = file_get_contents($filePath);
    // 解析 PKCS#12,第三个参数为密码,空字符串表示无密码
    if (openssl_pkcs12_read($pkcs12, $certs, '')) {
        $privateKey = $certs['pkey']; // 提取私钥资源
        $publicKey  = $certs['cert']; // 提取公钥证书(可选)

        $signedMsg = '';
        // 默认使用 SHA1 (OPENSSL_ALGO_SHA1)
        if (openssl_sign($strData, $signedMsg, $privateKey)) {
            // 签名成功,转为十六进制便于存储/传输
            return bin2hex($signedMsg);
        } else {
            return ''; // 签名失败
        }
    } else {
        return '0'; // PKCS#12 解析失败(密码错误或格式损坏)
    }
}
?>

关键技术点解析

openssl_pkcs12_read 优势

直接读取 .pfx / .p12 文件,无需预先用 OpenSSL 命令转换为 PEM 格式,简化了部署流程。第三个参数为证书密码,若证书无密码保护则传空字符串。

openssl_sign 默认算法与指定算法

  • 默认摘要算法为 OPENSSL_ALGO_SHA1。
  • 若使用 DSA 密钥,必须显式指定 OPENSSL_ALGO_DSS1:
    openssl_sign($data, $sig, $privKey, OPENSSL_ALGO_DSS1);
  • 支持的算法常量(需 PHP/OpenSSL 版本支持):
常量对应算法
OPENSSL_ALGO_DSS1DSA-SHA1
OPENSSL_ALGO_SHA1SHA1
OPENSSL_ALGO_SHA224SHA224
OPENSSL_ALGO_SHA256SHA256
OPENSSL_ALGO_SHA384SHA384
OPENSSL_ALGO_SHA512SHA512
OPENSSL_ALGO_RMD160RIPEMD-160
OPENSSL_ALGO_MD5MD5
OPENSSL_ALGO_MD4MD4
OPENSSL_ALGO_MD2MD2

返回值处理

  • openssl_sign 将二进制签名写入 $signedMsg(引用传参)。
  • bin2hex() 转为十六进制字符串,便于数据库存储、JSON 传输或 URL 传递。
  • 验签端需用 pack("H*", $hexSig) 还原为二进制。

完整调用示例

<?php
$data = "订单号: 20240101001, 金额: 100.00";
$signature = sign($data);

if ($signature && $signature !== '0') {
    echo "签名生成成功: " . $signature;
    // 存储 $signature 或传递给对方验签
} elseif ($signature === '0') {
    echo "证书解析失败,请检查 PFX 文件或密码";
} else {
    echo "签名生成失败,请检查私钥权限或数据格式";
}
?>

安全最佳实践

  • PFX 文件权限设为 600,仅所有者可读。
  • 生产环境建议使用 SHA256 及以上算法:openssl_sign($data, $sig, $privKey, OPENSSL_ALGO_SHA256)。
  • 私钥密码应通过环境变量或密钥管理系统注入,避免硬编码。
  • 定期轮换证书,监控签名失败日志。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved