エラーメッセージ
No supported key formats were found. Check that the input represents the contents of a PEM-encoded key file, not the path to such a file. (Parameter 'input')
別の表記
- An encrypted key was found, but no password was provided. Use ImportFromEncryptedPem to import this key. (Parameter 'input')
- Key is not a valid public or private key.
`ENCRYPTED PRIVATE KEY` ブロックの場合は「An encrypted key was found, but no password was provided. Use ImportFromEncryptedPem to import this key.」になります。
.NET System.Security.Cryptography — ArgumentException from AsymmetricAlgorithm.ImportFromPem
このエラーの意味
`ImportFromPem` は、このアルゴリズムのオブジェクトにインポートできるラベルを持つ PEM ブロックを文字列内で探しましたが、見つかりませんでした。このメソッドが受け取るのはファイル名ではなく PEM のテキストです。また、`ECDsa` オブジェクトは EC のラベル(`PRIVATE KEY`、`EC PRIVATE KEY`、EC 鍵を含む `PUBLIC KEY`)だけを、`RSA` オブジェクトは RSA のラベルだけを受け付けます。ラベルは合っていても中の鍵が別のアルゴリズムのものである場合は、代わりに「Key is not a valid public or private key.」というエラーになります。
発生する理由
ファイルの内容ではなくファイルパスを渡している
よくある`ImportFromPem("/keys/private.pem")` はパスの文字列から PEM のアーマーを探しますが、見つかりません。メッセージ中のヒントは、まさにこの間違いのためにあります。
RSA の PEM を ECDsa にインポートしている(またはその逆)
よくある`RSA PRIVATE KEY` / `RSA PUBLIC KEY` ブロックは `ECDsa.ImportFromPem` で、`EC PRIVATE KEY` は `RSA.ImportFromPem` で読み飛ばされます。
証明書または未対応のブロック
ときどき`CERTIFICATE`、`CERTIFICATE REQUEST`、`OPENSSH PRIVATE KEY` のブロックは、`ImportFromPem` が読み取る鍵の形式ではありません。
鍵が暗号化されている
ときどき暗号化された PKCS#8 には、パスワードを指定した `ImportFromEncryptedPem` が必要です。
修正方法
- 1.
ファイルの内容を正しいアルゴリズムに渡す
ファイルを読み込み、鍵のアルゴリズムに対応するオブジェクトを作成してください。暗号化された鍵には、暗号化鍵用のメソッドを使ってください。
csharp using var ecdsa = ECDsa.Create(); ecdsa.ImportFromPem(File.ReadAllText("/run/secrets/jwt-signing-key.pem")); // contents, not the path // encrypted PKCS#8: ecdsa.ImportFromEncryptedPem(File.ReadAllText(path), Environment.GetEnvironmentVariable("KEY_PASSPHRASE")); - 2.
証明書は証明書として読み込む
証明書の PEM を鍵としてインポートするのではなく、`X509Certificate2` から公開鍵を取り出してください。
csharp // .NET 9+: certificates are loaded with X509CertificateLoader, then the key is taken from them var cert = X509CertificateLoader.LoadCertificate(File.ReadAllBytes("cert.der")); using ECDsa? publicKey = cert.GetECDsaPublicKey();