Fehlermeldung
Could not parse PKey (OpenSSL::PKey::PKeyError)
Auch ausgegeben als
- OpenSSL::PKey::PKeyError: Could not parse PKey
- Neither PUB key nor PRIV key (OpenSSL::PKey::RSAError)
- invalid curve name (OpenSSL::PKey::ECError)
Wird die Ausnahme nicht abgefangen, gibt Ruby „…: Could not parse PKey (OpenSSL::PKey::PKeyError)“ aus. Die klassenspezifischen Konstruktoren lösen `OpenSSL::PKey::RSAError` / `ECError` mit eigenen Texten aus.
Ruby openssl gem — OpenSSL::PKey.read / OpenSSL::PKey::RSA.new / OpenSSL::PKey::EC.new
Was der Fehler bedeutet
`OpenSSL::PKey.read` hat jedes Schlüsselformat probiert, das OpenSSL kennt (PEM und DER, öffentlich und privat, verschlüsselt mit dem angegebenen Passwort), und keines hat funktioniert. Ruby gibt den genauen Grund von OpenSSL nicht weiter, deshalb steht derselbe Text für ein verstümmeltes PEM, eine falsche Passphrase und Daten, die gar kein Schlüssel sind. Die algorithmusspezifischen Konstruktoren scheitern ähnlich: `RSA.new` mit „Neither PUB key nor PRIV key“, `EC.new` mit „invalid curve name“ (dieser Konstruktor behandelt eine Eingabe, die sich nicht parsen lässt, als Kurvennamen).
Warum der Fehler auftritt
Zeilenumbrüche durch ein wörtliches \n ersetzt
häufigMehrzeilige Schlüssel in Umgebungsvariablen, Konfigurationsvariablen von Heroku/Render oder YAML-Strings landen oft als eine einzige Zeile, in der die Umbrüche als `\n` stehen.
Verschlüsselter Schlüssel ohne oder mit falschem Passwort
häufig`PKey.read(data)` ohne das zweite Argument kann einen verschlüsselten Schlüssel nicht entschlüsseln; ein falsches Passwort erzeugt denselben Fehler, keinen eigenen für das Passwort.
Kein Schlüssel, den OpenSSL lesen kann
gelegentlichEin öffentlicher Schlüssel im OpenSSH-Format (`ssh-ed25519 AAAA…`), ein JWK als JSON-Dokument oder eine Datei mit einer Zertifikatskette, die vor dem PEM-Block zusätzlichen Text enthält.
So behebst du den Fehler
- 1.
Zeilenumbrüche wiederherstellen und prüfen, was geladen wurde
Wandle die Zeichenfolgen `\n` wieder in Zeilenumbrüche um, lies den Schlüssel einmal beim Start ein und prüfe per Assertion seinen Typ und ob er privat ist.
ruby pem = ENV.fetch("JWT_PUBLIC_KEY").gsub("\\n", "\n") # restore real newlines key = OpenSSL::PKey.read(pem) raise "expected a public EC key" if key.private? || !key.is_a?(OpenSSL::PKey::EC) - 2.
Mehrzeilige Schlüssel dort speichern, wo sie intakt bleiben
Die verschlüsselten Credentials von Rails oder eine eingebundene Secret-Datei bewahren das PEM unverändert, anders als einzeilige Umgebungsvariablen.
ruby # Rails: keep multi-line keys in encrypted credentials instead of ENV # bin/rails credentials:edit # jwt: # public_key: | # -----BEGIN PUBLIC KEY----- # ... key = OpenSSL::PKey.read(Rails.application.credentials.dig(:jwt, :public_key))