エラーメッセージ
Failed to read asymmetric key
Node.js crypto — e.g. code ERR_OSSL_ASN1_WRONG_TAG
このエラーの意味
createPublicKey()(または crypto.verify() など、公開鍵を DER で受け取るあらゆる呼び出し)に渡されたバイト列の ASN.1 構造が、指定した type と一致しませんでした。たとえば type: "spki" を指定したのに、バイト列が実際には SEC1 の EC 秘密鍵だった場合です。OpenSSL はタグが誤っているとわかるところまで解析し、そこで停止しました。(createPrivateKey() やラベルの誤った PEM では、同じ種類の不一致が OpenSSL 自身の文言、たとえば「error:068000A8:asn1 encoding routines::wrong tag」で報告されます。)付随するコード(ERR_OSSL_ASN1_WRONG_TAG とその類似コード)は、ASN.1 レベルの不一致を示しています。解析できるものが何も見つからなかったことを意味する DECODER routines の「unsupported」エラーとは異なり、このエラーは、バイト列が指定した type とは別の構造だと識別できたことを意味します。
発生する理由
指定した type がバイト列と一致しない
よくあるDER には複数のコンテナー形式があります。公開鍵用の SPKI、秘密鍵用の PKCS#8、レガシーな EC 秘密鍵用の SEC1、レガシーな RSA 用の PKCS#1 です。SEC1 や PKCS#8 の秘密鍵、あるいは証明書全体に対して type: "spki" を指定すると、すぐにタグのチェックで失敗します。
Base64 がデコードされていない、または二重にデコードされている
よくあるbase64 のテキストを format: "der" で渡す(OpenSSL が ASCII を ASN.1 として解析してしまう)場合も、ヘッダー行を含む PEM 全体に Buffer.from(pem, "base64") を使う場合も、タグの誤った意味のないバイト列ができあがります。
鍵の構造ではなく生の EC 点
ときどき非圧縮の点を表す 65 バイト(0x04‖X‖Y)は DER ではなく、SPKI の内部に収められるペイロードです。これを直接 createPublicKey に渡すと失敗します。SPKI で包むか、JWK または WebCrypto の raw インポートで読み込む必要があります。
修正方法
- 1.
構造を特定してから、正しく指定する
asn1parse は外側の構造を出力します。SPKI は AlgorithmIdentifier を含む SEQUENCE で始まり、PKCS#8 はバージョンを表す INTEGER 0 で、SEC1 の EC 鍵は INTEGER 1 で始まります。
bash openssl asn1parse -inform der -in key.der | head -5 - 2.
Node のオプションをコンテナー形式に合わせる
コンテナー形式がわかれば、あとは機械的に対応付けられます。
js // SPKI public key createPublicKey({ key: der, format: "der", type: "spki" }); // PKCS#8 private key createPrivateKey({ key: der, format: "der", type: "pkcs8" }); // SEC1 (BEGIN EC PRIVATE KEY) private key createPrivateKey({ key: der, format: "der", type: "sec1" }); - 3.
レガシーなコンテナー形式は入口で一度だけ変換する
保存する形式を PKCS#8/SPKI に統一し、アプリケーションのコードが推測しなくて済むようにしてください。
bash openssl pkey -in legacy-ec.pem -out key-pkcs8.pem # any private → PKCS#8 openssl pkey -in key-pkcs8.pem -pubout -out pub-spki.pem # derive SPKI public