Message d’erreur
openssl_verify(): Supplied key param cannot be coerced into a public key
Également affiché sous la forme
- 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
Le nom de la fonction varie (`openssl_verify`, `openssl_sign`, `openssl_seal`, `openssl_public_encrypt`…), de même que le type de clé (« public key » / « private key »). Avec `display_errors` activé, PHP ajoute le préfixe « Warning: ».
PHP OpenSSL extension — warning from openssl_verify / openssl_sign / openssl_seal
Ce que cela signifie
Les fonctions OpenSSL de PHP acceptent une clé sous forme de texte PEM, de chemin `file://` ou d’objet clé, et la valeur que vous avez passée n’a pas pu être convertie en clé du type requis (publique pour vérifier, privée pour signer). C’est un avertissement, pas une exception : la fonction renvoie `false` (ou `-1`), et le code qui teste uniquement `=== 1` le traite silencieusement comme une « signature invalide ». La raison sous-jacente fournie par OpenSSL est disponible via `openssl_error_string()`.
Pourquoi cela se produit
PEM contenant des \n littéraux issus d’une variable d’environnement
fréquenteLes clés stockées dans des fichiers `.env`, des variables de CI ou du JSON contiennent souvent les deux caractères `\` et `n` au lieu de sauts de ligne. OpenSSL ne peut pas analyser un tel PEM.
Un chemin de fichier sans file://
fréquenteUn chemin nu comme `/etc/app/private.pem` est traité comme du texte PEM, et l’appel échoue. PHP attend `file:///etc/app/private.pem` ou le contenu du fichier.
Un certificat, une clé privée ou une clé SSH là où une clé publique est attendue
occasionnelle`openssl_verify` accepte un certificat ou une clé publique ; une clé publique OpenSSH (`ssh-ed25519 AAAA…`) ou une chaîne JSON de JWK n’est pas du PEM.
Une clé privée chiffrée sans phrase de passe
occasionnellePasser un PEM `ENCRYPTED PRIVATE KEY` sous forme de chaîne à `openssl_sign` ne peut pas fonctionner ; chargez-le d’abord avec `openssl_pkey_get_private($pem, $passphrase)`.
Comment corriger l’erreur
- 1.
Charger la clé explicitement et faire apparaître la raison donnée par OpenSSL
`openssl_pkey_get_public` / `_private` renvoient `false` en cas d’échec ; appelez `openssl_error_string()` jusqu’à épuisement des messages pour journaliser la cause, et arrêtez-vous au lieu de poursuivre avec une vérification qui a échoué.
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.
Utiliser file:// pour les chemins de fichier et transmettre les phrases de passe
Rendez explicite la source de la clé : soit le contenu PEM, soit un URI `file://`, plus la phrase de passe pour les clés chiffrées.
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);