PHP:openssl_verify 无法使用 ECDSA 密钥

PHP: openssl_verify not working with ECDSA keys

我需要以下 "pseudo" 代码的帮助:

<?php

$stringToVerify = '50.009781OK101092014125505';
$ECDSA =     '3045022100b4b4064158cb12f5b3d902e1e4487e0c6dfafd96b5bb5ab9765fc088e054d67e0220153    f9bb5da20441c68ff0c3e8ba28cfe048e5c3152fc8c890def156cf09d5540';
$publicKey = "-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEaq6djyzkpHdX7kt8DsSt6IuSoXjp
WVlLfnZPoLaGKc/2BSfYQuFIO2hfgueQINJN3ZdujYXfUJ7Who+XkcJqHQ==
-----END PUBLIC KEY-----";

var_dump(openssl_verify($stringToVerify, pack("H*", $ECDSA), $publicKey,     OPENSSL_ALGO_SHA256));
var_dump(openssl_error_string());

openssl_verify() 将始终 return 非真值,而 openssl_error_string() 将 return 错误消息:'error:0906D06C:PEM routines:PEM_read_bio:no start line'

哪里可能有问题?为什么 openssl_verify() 不会 return TRUE?

OpenSSL 版本为 1.0.1r 2016 年 1 月 28 日

error:0906D06C:PEM routines:PEM_read_bio:no start line 不是致命的。这意味着它没有找到证书和私钥,这没关系,因为在这种情况下只有一个 public/private 密钥。

openssl_verify() returns -1 失败,1 如果签名正确,0 如果不正确。因此,您应该检查所有 3 个值,而不仅仅是 true 或 false。

您应该检查 openssl_verify 的 return 值是否 -1 指示失败。如果是 returns 0,那么密钥是有效的,但是签名无效,数据被篡改,或者使用了错误的 public 密钥进行验证。

这是一个完整的示例:

<?php

$stringToSign = "hey this is some data I want to sign to confirm I said it and no one else...";
$privateKey =
"-----BEGIN RSA PRIVATE KEY-----
MIIEpQIBAAKCAQEA0PWnPjB5x8Xs+uV0GRCGGE8xlLU67sx6CDdAU7FBsBe8X7pt
065MAUwrtRQvIhyKhd9wRg8LvgWm7vYnYi5tkdodOhRyVw+jd7Id9CsQwUNNG+JZ
vrEmHKCTXvWbv/fmL5DTCkRxoJj3KdNqUYA6M+JcGahgpGnsRmvWQ2mz4IZZi5ur
vjSPPdrBSWgts5uIv5tNfEwuEzbJtIENn0tysoksIiG/n8edBbxlTqCo8OJVfy1n
h21TdBEHsi9V0NyEtqAFKdHaZscA3yj9k2mWuqSg1c0VnGJ/+OmOvgLkDlz3f7vH
t7ULJxV/iyNdugh5XUD1YKRwhMqBqfTNlKyFvwIDAQABAoIBABEsPyRjQ37hi0pL
VTFCJGMXDxITmtZJQ7YtJEI8jRN1v+t2HNSKvIBWzDjDgeQhyFicNlPrpKFnQYLe
A/qTqjmUXVaKm6MADAUoREHu0B+x8kJaZdnAIUu0/qeNM9GhA+/gzRdI7LWwHI/5
agFsslvVPJB3QAoDEoHvFtrPcxL+kY+wZu8RUYG6TCX/QxD45iZhQkWFH6I6tXh+
5wO1Dt0sx1iQJYkaI9/iHGkKS04hnNCQKPSdBLx0p+w87W9aF3+hoafRGMLsHL8S
mzQTFTHryYdrczjFhFypPhgCm+gdm8OlhjpuRHdmEV6jm40snnPyq9w9gm1Etge9
v0otEjECgYEA7z8WOw0NGb+UHx8F+YKyaaVigkN/Pal0tBbBG/XIF2hubbldr3Z8
/XCfmY8sIdQvxOusSfD1aFCxS34t8V6kAerQKZ6p4+W4xb7+dF9/qfCqJXzQttug
M8EujgAdqlS+G/3FKzHBWmfTDlymLsldH2dC2I6U+Jo5kAzPyS5SxLsCgYEA35ef
E79OaCKNFGpK9VgsLnEKd9DtZS3abzOkx5242VRjWIjrsvEgLfuvLSGGYgSaeCMY
edsCQ3mfmS2Yjiov0eZ4b2PcK+16ndaGQceHwuoP/eeH/BGe+eLcDF/xBFx7yRnn
sVgDhePthBCwOOJm7M26cCVdMmO3GMHxopXdNM0CgYEAlfQvxeFfRbU7bOov/3y4
wNjlTopp1UdCG6JrdU/vEyTkmidmHhUhMGUH0+LWIXnyWvXwbgP2fWSeS5gRycis
+Xqo8H0/NNWGo4Mbz+sPhH+Q1aBO3V35IpdBy8Us0tb8tWSw0WsFKtoKgmT10Dtr
/8PkNQHhQ5S+4Zf2IL3FKQMCgYEAy4A0SMTVl/HadbpIfwTBMYOxA1wktPIG3S8j
yorCswsbYHk+DJ9pqnBn/6uDo7KM5MsMe9vZM5B+sevN7ZZ375LUCo3Y1iJOd1nI
2BXCeqSN6YnROprPFqBjpt+rfUyvXVk2hzKUAkhw5MJLoXpuMxkLlwZqzHH1M5NR
WakMrAECgYEA4Ij7J3591daJbS5+pFK7MujrSg6TTi2etyyXcNO6xIkEbiX69MIU
DZh9GfAVkh6k/WaA2MuThI39TZJiF0nBU+irQttK6LeVhZ2MK+dEJh7rTy1b7zv1
WXLfkc1viK7cnC2ROOChmRm64GURupdf7ACsR2r+vbTSEoevWKfXwIk=
-----END RSA PRIVATE KEY-----";

$publicKey =
"-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0PWnPjB5x8Xs+uV0GRCG
GE8xlLU67sx6CDdAU7FBsBe8X7pt065MAUwrtRQvIhyKhd9wRg8LvgWm7vYnYi5t
kdodOhRyVw+jd7Id9CsQwUNNG+JZvrEmHKCTXvWbv/fmL5DTCkRxoJj3KdNqUYA6
M+JcGahgpGnsRmvWQ2mz4IZZi5urvjSPPdrBSWgts5uIv5tNfEwuEzbJtIENn0ty
soksIiG/n8edBbxlTqCo8OJVfy1nh21TdBEHsi9V0NyEtqAFKdHaZscA3yj9k2mW
uqSg1c0VnGJ/+OmOvgLkDlz3f7vHt7ULJxV/iyNdugh5XUD1YKRwhMqBqfTNlKyF
vwIDAQAB
-----END PUBLIC KEY-----";

$signature = null;
$alg       = OPENSSL_ALGO_SHA256;

if (openssl_sign($stringToSign, $signature, $privateKey, $alg)) {
    echo "Successfully signed data.\n";

    $signature = base64_encode($signature); // as might be done in transport

    // verify which should succeed
    $success = openssl_verify($stringToSign, base64_decode($signature), $publicKey, $alg);

    if ($success === -1) {
        echo "openssl_verify() failed with error.  " . openssl_error_string() . "\n";
    } elseif ($success === 1) {
        echo "Signature verification was successful!\n";
    } else {
        echo "Signature verification failed.  Incorrect key or data has been tampered with\n";
    }

    // verify which should fail because data has been tampered with
    $stringToSign .= "\nI am evil and demand you wire ,000,000,000 to me.";

    $success = openssl_verify($stringToSign, base64_decode($signature), $publicKey, $alg);

    if ($success === -1) {
        echo "openssl_verify() failed with error.  " . openssl_error_string() . "\n";
    } elseif ($success === 1) {
        echo "Signature verification was successful!\n";
    } else {
        echo "Signature verification failed.  Incorrect key or data has been tampered with!\n";
    }
} else {
    echo "openssl_sign() failed.  " . openssl_error_string() . "\n";
}