以下 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 解析失败(密码错误或格式损坏)
}
}
?>
直接读取 .pfx / .p12 文件,无需预先用 OpenSSL 命令转换为 PEM 格式,简化了部署流程。第三个参数为证书密码,若证书无密码保护则传空字符串。
OPENSSL_ALGO_SHA1。OPENSSL_ALGO_DSS1:openssl_sign($data, $sig, $privKey, OPENSSL_ALGO_DSS1);| 常量 | 对应算法 |
|---|---|
| OPENSSL_ALGO_DSS1 | DSA-SHA1 |
| OPENSSL_ALGO_SHA1 | SHA1 |
| OPENSSL_ALGO_SHA224 | SHA224 |
| OPENSSL_ALGO_SHA256 | SHA256 |
| OPENSSL_ALGO_SHA384 | SHA384 |
| OPENSSL_ALGO_SHA512 | SHA512 |
| OPENSSL_ALGO_RMD160 | RIPEMD-160 |
| OPENSSL_ALGO_MD5 | MD5 |
| OPENSSL_ALGO_MD4 | MD4 |
| OPENSSL_ALGO_MD2 | MD2 |
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 "签名生成失败,请检查私钥权限或数据格式";
}
?>
600,仅所有者可读。openssl_sign($data, $sig, $privKey, OPENSSL_ALGO_SHA256)。