PHP: openssl_verify not working with ECDSA keys

随声附和 提交于 2019-12-25 18:27:25

问题


I need some help with the following "pseudo" code:

<?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() will always return non-TRUE value and the openssl_error_string() will return error message: 'error:0906D06C:PEM routines:PEM_read_bio:no start line'

Where might be a problem? Why openssl_verify() won't return TRUE?

OpenSSL version is 1.0.1r 28 Jan 2016


回答1:


The error:0906D06C:PEM routines:PEM_read_bio:no start line is non-fatal. That means it didn't find a certificate along with the private key which is okay since there is only a public/private key in this case.

openssl_verify() returns -1 on failure, 1 if the signature is correct and 0 if it is incorrect. Because of this you should be checking for all 3 values, not just true or false.

You should check the return value of openssl_verify for -1 indicating failure. If it returns 0, then the key is valid but either the signature is invalid, the data was tampered with, or the wrong public key was used for verification.

Here's a fully illustrated example:

<?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 $1,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";
}


来源:https://stackoverflow.com/questions/36433799/php-openssl-verify-not-working-with-ecdsa-keys

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!