以下 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);
}
?>
仅当返回 1 时才视为验签通过。
OPENSSL_ALGO_SHA1,适用于 RSA 签名。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();
}
?>
-----BEGIN PUBLIC KEY-----)。openssl_error_string() 获取详细错误信息。OPENSSL_ALGO_DSS1,否则会返回 -1。