マイナンバーカードを Google のセキュリティキーにする — Ed25519 で弾かれ、ES256(per-RP 派生)で通すまで

前々回、マイナンバーカードを Safari の WebAuthn 認証器にして webauthn.io で動かしました。今回はそれを Google アカウントのセキュリティキー/パスキーとして登録しようとして一度弾かれ、原因を突き止めて通すまでの記録です。鍵になるのは「どの署名アルゴリズムを出すか」でした。

webauthn.io では動くのに、Google では「変更を保存できませんでした」

拡張は webauthn.io(Ed25519 を選べる実 RP)では登録も認証も成功しました。AAGUID が all-zero なのも、これが Touch ID ではなく自前の認証器である証拠です。ところが Google で同じことをやると、PIN ポップアップすら出ずに 変更を保存できませんでした

コンソールを見ると、拡張の navigator.credentials override は Google の全ドメインで効いていました。つまり横取りはできている。問題はその先――我々の実装が Ed25519(COSE alg = -8, EdDSA)しか作れず、Google はそれを要求していなかったのです。我々の拡張は「提示された pubKeyCredParams に -8 が無ければ即拒否」していたため、カードに触る前に止まっていました。

安直な回避策がダメな理由

「ならカードの JPKI RSA 鍵をそのまま RS256 credential として使えばいい」と一瞬思いますが、これは筋が悪い。マイナンバーカードの認証用 RSA 鍵は 1 枚に 1 つなので、それを直接 credential 公開鍵にすると――

  • 全 RP で同じ公開鍵になり、サイト横断で名寄せされる(プライバシー崩壊)
  • 公式の JPKI 公開鍵そのものを各サイトに晒す

この設計が大事にしていた「RP ごとに別鍵(per-RP 非連結)」「JPKI 由来を漏らさない」が両方壊れます。

正しい解:同じ種から P-256 を派生してソフトで署名

そもそも我々の Ed25519 は、カードの RSA 署名を「種(seed)」にしてソフトで鍵を導出・署名しています(カードは種の供給だけ)。ならば同じ種から P-256(ES256)鍵を派生してソフトで ECDSA 署名すればいい。これなら:

  • RP ごと(rpId + userId)に別鍵 → per-RP 非連結を維持
  • JPKI 鍵は晒さない(種にしか使わない)→ cert leak ゼロを維持
  • Google が要求する ES256(-7) を満たせる

実装は Ed25519 経路と並列に足しました:

  • Rust(FFI):種 → P-256 秘密鍵を導出 → ECDSA(SHA-256) で署名、公開鍵 (x, y) を返す関数を追加(p256 クレート)
  • Swift / bridgingalg(ed25519 / es256)で分岐。ES256 署名は DER 可変長
  • background.js:RP の pubKeyCredParams から alg を選択(EdDSA 優先 → 無ければ ES256)、COSE は EC2 鍵(kty=2 / -7 / P-256 / x / y)を構築、credential に alg を保存して認証時に同じ鍵種で署名

結果:Google で登録成功

ES256 を足したら、Google でも PIN ポップアップが出てカードで登録できました。RP が EdDSA を出せば Ed25519、ES256 しか出さなければ ES256、と自動で切り替わります。マイナンバーカードが、Ed25519 系・ES256 系どちらの実 WebAuthn サービスでも認証器として動くようになりました。

正直な限界:これは YubiKey ではない

誤解しないよう書いておくと、この方式は鍵の耐タンパー性では YubiKey に劣ります。カードは種を供給するだけで、実際の鍵導出と署名は PC のソフト上で行うため、署名の瞬間にホストがマルウェア汚染されていれば鍵を抜かれ得ます(YubiKey は鍵がチップから出ないのでこれが起きない)。

  • 所持要素(カード+PIN が無ければ使えない)としては YubiKey 同等で、フィッシング耐性もある
  • 鍵の非抽出性では劣る。「耐タンパー」と「per-RP 非連結」をカード 1 枚で両取りするのは原理的に難しい(カード内署名にすると全 RP 同一鍵になる)

なので位置づけは「YubiKey 代替」よりも「誰もが持つカードを使った、所持+PIN の認証器 / 紛失リカバリ手段」。足りない本人性の担保は、別途 OIDC(デジタル認証アプリ)を登録時に噛ませるハイブリッド(前回の記事)で補う、という設計です。

コードはこちら(実験的 skeleton):Ryujiyasu/myna-fido-safari。元になった jpki/myna に感謝します。

コメント

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

IP: 取得中...
216.73.216.68216.73.216.68