openssl_verify

(PHP 4 >= 4.0.4, PHP 5, PHP 7, PHP 8)

openssl_verify验证签名

描述

openssl_verify(
    字符串 $data,
    字符串 $signature,
    OpenSSLAsymmetricKey|OpenSSLCertificate|数组|字符串 $public_key,
    字符串|整数 $algorithm = OPENSSL_ALGO_SHA1
): 整数|false

openssl_verify() 验证指定的 datasignature 是否正确,使用与 public_key 关联的公钥。这必须是与用于签名的私钥相对应的公钥。

参数

data

之前用于生成签名的字符串数据

signature

openssl_sign() 或类似方法生成的原始二进制字符串

public_key

OpenSSLAsymmetricKey - 由 openssl_get_publickey() 返回的密钥

字符串 - PEM 格式的密钥(例如 -----BEGIN PUBLIC KEY----- MIIBCgK...

algorithm

整数 - 以下之一 签名算法.

字符串 - 由 openssl_get_md_methods() 返回的有效字符串,例如 "sha1WithRSAEncryption" 或 "sha512"

返回值

如果签名正确,则返回 1;如果签名不正确,则返回 0;如果出错,则返回 -1 或 false

变更日志

版本 描述
8.0.0 public_key 现在接受 OpenSSLAsymmetricKeyOpenSSLCertificate 实例;以前,接受类型为 OpenSSL keyOpenSSL X.509资源

示例

示例 #1 openssl_verify() 示例

<?php
// 假设 $data 和 $signature 包含数据和签名

// 从证书中获取公钥并准备它
$pubkeyid = openssl_pkey_get_public("file://src/openssl-0.9.6/demos/sign/cert.pem");

// 指示签名是否正确
$ok = openssl_verify($data, $signature, $pubkeyid);
if (
$ok == 1) {
echo
"good";
} elseif (
$ok == 0) {
echo
"bad";
} else {
echo
"ugly, error checking signature";
}
// 从内存中释放密钥
openssl_free_key($pubkeyid);
?>

示例 #2 openssl_verify() 示例

<?php
// 您想要签名的数据
$data = 'my data';

// 创建新的私钥和公钥
$private_key_res = openssl_pkey_new(array(
"private_key_bits" => 2048,
"private_key_type" => OPENSSL_KEYTYPE_RSA,
));
$details = openssl_pkey_get_details($private_key_res);
$public_key_res = openssl_pkey_get_public($details['key']);

// 创建签名
openssl_sign($data, $signature, $private_key_res, "sha256WithRSAEncryption");

// 验证签名
$ok = openssl_verify($data, $signature, $public_key_res, OPENSSL_ALGO_SHA256);
if (
$ok == 1) {
echo
"valid";
} elseif (
$ok == 0) {
echo
"invalid";
} else {
echo
"error: ".openssl_error_string();
}
?>

参见

添加说明

用户贡献说明 8 notes

Stiv
18 年前
我终于找到了验证签名的方法。文档中的示例不起作用。下面的代码有效!

<?php
// 假设 $data 包含要签名的数据

// 从文件获取证书并准备它
$fp = fopen("path/file.pem", "r");
$cert = fread($fp, 8192);
fclose($fp);

// 指示签名是否正确
// 使用证书,而不是公钥
$ok = openssl_verify($data, $signature, $cert);
if (
$ok == 1) {
echo
"good";
} elseif (
$ok == 0) {
echo
"bad";
} else {
echo
"ugly, error checking signature";
}
?>
mikey at badpenguins dot com
14 年前
我花了几天时间浏览 PHP OpenSSL 文档,试图弄清楚如何执行看似简单的任务 - 给定两个 PEM 编码的证书,一个是另一个的签名者吗?在 openssl_verify() 文档或注释中,没有解释在哪里获取现有证书的签名。openssl_x509_parse() 函数看起来很有希望,但它是一个不稳定的 API,可能会发生变化。

我不得不编写自己的代码来确定一个证书是否签署了另一个证书,它位于这里:http://badpenguins.com/source/misc/isCertSigner.php?viewSource

简而言之,我学到了以下几点...

签署的 X.509 证书中的签名数据包含有关签名的 DER 格式数据,这些数据使用签名者的公钥加密。该数据包含原始主体证书的哈希值以及有关用于创建签名的加密算法的信息。

因此,您需要获取此签名数据以及原始证书的副本,其中已删除发行者和签名序列。使用发行者使用的相同算法对原始证书的副本(不含发行者/签名序列)进行哈希处理,如果哈希值匹配,则您拥有签署证书的发行者证书。
meint dot post at bigfoot dot com
23 年前
任何尝试使基于 Win32 CryptoAPI 的数字签名组件与 openssl_verify() 函数一起工作的人应该知道,CryptoAPI PKCS1 (RSA) 方法使用反向顺序的字节,而 openssl_verify() 方法期望正确格式化的 PKCS1 数字签名(应如此)。我通过艰难的方式学到了这一点,花了一些时间才弄清楚。VBScript 中一个简单的解决方案来反转字节顺序

N = Len(Blob.Hex)

' 使用十六进制格式反转签名中的字节
For i = 1 To N - 1 Step 2
s = Mid(Blob, i, 2) & s
Next

s 包含反向顺序的数字签名。Blob 是一个任意二进制容器。

以十六进制格式发送签名,并在 PHP 中使用 hex2bin 方法将其转换为 openssl_verify() 的正确格式,例如

function hex2bin($data) {

$len = strlen($data);
return pack("H" . $len, $data);

}

就是这样,希望对您有所帮助。顺便说一句,我使用了 ASPEncrypt 在 Win32 平台上玩弄。它只适用于 Internet Explorer,但您也可以使用 Java Applet 并避免上述所有问题 :-)
peter dot labos at gmail dot com
6 年前
openssl_verify() 即使在 false 时也会填充 openssl_error_string()。

当 openssl_verify() 返回 0 时,openssl_error_string() 将填充为 1。
我花了很长时间才理解,而我对 openssl 的下一次调用在进行错误检查时失败了。

<?php
$c
= file_get_contents($filename);
$publicKey = openssl_pkey_get_public($c);
$result = openssl_verify('freedom', 'someirrelevantnosign', $publicKey);

$error = "";

while (
$msg = openssl_error_string() !== false) {
$error .= $msg;
}

if (!empty(
$error)) {
echo
$error; // 1
}
steve dot venable at lmco dot com
22 年前
关于 openssl_verify()(以及其他一些函数)的一点说明。公钥来自任何支持格式的证书(如示例所示,使用 openssl_get_publickey() 获取资源 ID)。但在经过一些试错之后,我发现签名字符串必须是二进制的。虽然不会出现错误,但传递 base64 格式的签名字符串(PEM 格式?),您只会得到不匹配。当我自行执行 base64 解码时,验证返回匹配(返回值 1)。您只需删除开始/结束行并使用 'base64_decode()' 函数的输出即可。
phpdev at fpierrat dot fr
2 年前
如文档所述:“如果签名正确,则返回 1;如果签名不正确,则返回 0;如果发生错误,则返回 -1 或 false。”

在第二个示例以及 Stiv 的说明中,以下条件将匹配 0 或 false,它们具有不同的含义
elseif ($ok == 0) {
echo "bad";
}

应在此处进行相同的测试(===)而不是相等测试(==)
elseif ($ok === 0) {
echo "bad";
}
---
var_dump(0==false); //==> true
var_dump(0===false);//==> false
attila dot m dot magyar at gmail dot com
9 年前
mikey at badpenguins dot com -- 使用 openssl_x509_checkpurpose() 似乎可以在 php 中验证 X509 证书链
jeremie dot gomez at gmail dot com
12 年前
实际上可以使用公钥作为第三个参数,而不是证书。

如果您无法使其正常工作,请确保

1) 您的公钥格式正确。它似乎必须包含 ----BEGIN PUBLIC KEY---- 和 ----END PUBLIC KEY----

2) 您的签名采用二进制格式。您可以使用 php base64_decode 来完成此操作。
To Top