Skip to content
ecdsa.com
PHP OpenSSL extensionPHP

Error message

openssl_verify(): Supplied key param cannot be coerced into a public key

Also printed as

  • openssl_sign(): Supplied key param cannot be coerced into a private key
  • Warning: openssl_verify(): Supplied key param cannot be coerced into a public key

The function name varies (`openssl_verify`, `openssl_sign`, `openssl_seal`, `openssl_public_encrypt`…), and so does the key kind ("public key" / "private key"). With `display_errors` on, PHP prefixes "Warning: ".

PHP OpenSSL extension — warning from openssl_verify / openssl_sign / openssl_seal

What it means

PHP's OpenSSL functions accept a key as PEM text, a `file://` path, or a key object, and the value you passed could not be turned into a key of the required kind (public for verify, private for sign). This is a warning, not an exception: the function returns `false` (or `-1`), and code that checks only for `=== 1` silently treats it as "invalid signature". The underlying OpenSSL reason is available through `openssl_error_string()`.

Why it happens

How to fix it

  1. 1.

    Load the key explicitly and surface OpenSSL's reason

    `openssl_pkey_get_public` / `_private` return `false` on failure; drain `openssl_error_string()` to log why, and stop instead of continuing with a failed verification.

    php
    $pem = str_replace('\\n', "\n", getenv('JWT_PUBLIC_KEY'));   // undo escaped newlines
    $publicKey = openssl_pkey_get_public($pem);
    if ($publicKey === false) {
        while ($msg = openssl_error_string()) {
            error_log($msg);                                     // the real OpenSSL reason
        }
        throw new RuntimeException('JWT_PUBLIC_KEY is not a usable public key');
    }
    $ok = openssl_verify($data, $signature, $publicKey, OPENSSL_ALGO_SHA256) === 1;
  2. 2.

    Use file:// for paths and pass passphrases

    Make the key source explicit: either the PEM contents or a `file://` URI, plus the passphrase for encrypted keys.

    php
    // Paths need the file:// scheme; encrypted keys need their passphrase.
    $privateKey = openssl_pkey_get_private('file:///etc/app/private.pem', getenv('KEY_PASSPHRASE') ?: null);

Related errors

Browse the full signature error database