Saltar al contenido
ecdsa.com
PHP OpenSSL extensionPHP

Mensaje de error

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

También se muestra como

  • 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

El nombre de la función varía (`openssl_verify`, `openssl_sign`, `openssl_seal`, `openssl_public_encrypt`…), y también el tipo de clave («public key» / «private key»). Con `display_errors` activado, PHP antepone «Warning: ».

PHP OpenSSL extension — warning from openssl_verify / openssl_sign / openssl_seal

Qué significa

Las funciones OpenSSL de PHP aceptan una clave como texto PEM, como ruta `file://` o como objeto de clave, y el valor que pasas no se pudo convertir en una clave del tipo requerido (pública para verificar, privada para firmar). Es una advertencia, no una excepción: la función devuelve `false` (o `-1`), y el código que solo comprueba `=== 1` lo trata en silencio como «firma no válida». El motivo subyacente de OpenSSL está disponible mediante `openssl_error_string()`.

Por qué ocurre

Cómo solucionarlo

  1. 1.

    Cargar la clave explícitamente y mostrar el motivo de OpenSSL

    `openssl_pkey_get_public` / `_private` devuelven `false` si fallan; llama a `openssl_error_string()` hasta vaciar la cola para registrar el motivo, y detente en lugar de continuar con una verificación fallida.

    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.

    Usar file:// para las rutas de archivo y pasar las frases de contraseña

    Indica explícitamente el origen de la clave: o bien el contenido PEM, o bien un URI `file://`, además de la frase de contraseña para las claves cifradas.

    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);

Errores relacionados

Explorar toda la base de datos de errores de firma