Fehlermeldung
openssl_verify(): Supplied key param cannot be coerced into a public key
Auch ausgegeben als
- 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
Der Funktionsname variiert (`openssl_verify`, `openssl_sign`, `openssl_seal`, `openssl_public_encrypt` …), ebenso die Schlüsselart („public key“ / „private key“). Ist `display_errors` aktiv, stellt PHP „Warning: “ voran.
PHP OpenSSL extension — warning from openssl_verify / openssl_sign / openssl_seal
Was der Fehler bedeutet
Die OpenSSL-Funktionen von PHP akzeptieren einen Schlüssel als PEM-Text, als Pfad mit `file://` oder als Schlüsselobjekt, und der übergebene Wert ließ sich nicht in einen Schlüssel der benötigten Art umwandeln (öffentlich zum Prüfen, privat zum Signieren). Das ist eine Warnung, keine Ausnahme: Die Funktion gibt `false` (oder `-1`) zurück, und Code, der nur auf `=== 1` prüft, behandelt das stillschweigend als „ungültige Signatur“. Den zugrunde liegenden Grund von OpenSSL liefert `openssl_error_string()`.
Warum der Fehler auftritt
PEM mit wörtlichem \n aus einer Umgebungsvariable
häufigSchlüssel, die in `.env`-Dateien, CI-Variablen oder JSON gespeichert sind, enthalten statt Zeilenumbrüchen oft die beiden Zeichen `\` und `n`. OpenSSL kann ein solches PEM nicht parsen.
Ein Dateipfad ohne file://
häufigEin nackter Pfad wie `/etc/app/private.pem` wird als PEM-Text behandelt und scheitert. PHP braucht `file:///etc/app/private.pem` oder den Inhalt der Datei.
Ein Zertifikat, ein privater Schlüssel oder ein SSH-Schlüssel statt des erwarteten öffentlichen Schlüssels
gelegentlich`openssl_verify` akzeptiert ein Zertifikat oder einen öffentlichen Schlüssel; ein öffentlicher OpenSSH-Schlüssel (`ssh-ed25519 AAAA…`) oder ein JWK als JSON-String ist kein PEM.
Ein verschlüsselter privater Schlüssel ohne Passphrase
gelegentlichEin PEM mit `ENCRYPTED PRIVATE KEY` als String an `openssl_sign` zu übergeben, kann nicht funktionieren; lade es zuerst mit `openssl_pkey_get_private($pem, $passphrase)`.
So behebst du den Fehler
- 1.
Schlüssel explizit laden und den Grund von OpenSSL sichtbar machen
`openssl_pkey_get_public` / `_private` geben bei einem Fehler `false` zurück; ruf `openssl_error_string()` so lange auf, bis keine Meldung mehr kommt, protokolliere damit den Grund und brich ab, statt mit einer fehlgeschlagenen Prüfung weiterzumachen.
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.
Für Dateipfade file:// verwenden und Passphrasen übergeben
Gib die Quelle des Schlüssels eindeutig an: entweder den PEM-Inhalt oder einen URI mit `file://`, dazu bei verschlüsselten Schlüsseln die Passphrase.
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);