Pular para o conteúdo
ecdsa.com
PHP OpenSSL extensionPHP

Mensagem de erro

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

Também aparece 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

O nome da função varia (`openssl_verify`, `openssl_sign`, `openssl_seal`, `openssl_public_encrypt`…), assim como o tipo de chave (“public key” / “private key”). Com `display_errors` ativado, o PHP acrescenta o prefixo “Warning: ”.

PHP OpenSSL extension — warning from openssl_verify / openssl_sign / openssl_seal

O que significa

As funções OpenSSL do PHP aceitam uma chave como texto PEM, um caminho `file://` ou um objeto de chave, e o valor que você passou não pôde ser convertido em uma chave do tipo exigido (pública para verificar, privada para assinar). É um aviso, não uma exceção: a função retorna `false` (ou `-1`), e um código que só verifica `=== 1` trata isso silenciosamente como “assinatura inválida”. O motivo real informado pelo OpenSSL está disponível via `openssl_error_string()`.

Por que acontece

Como corrigir

  1. 1.

    Carregar a chave explicitamente e expor o motivo do OpenSSL

    `openssl_pkey_get_public` / `_private` retornam `false` em caso de falha; chame `openssl_error_string()` até esvaziar a fila para registrar o motivo no log, e interrompa em vez de continuar com uma verificação que falhou.

    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:// em caminhos de arquivo e passar as frases secretas

    Deixe explícita a origem da chave: ou o conteúdo PEM, ou uma URI `file://`, além da frase secreta para chaves criptografadas.

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

Erros relacionados

Ver toda a base de erros de assinatura