macOSのSecure EnclaveでSSH鍵を守る——鍵はハードウェアから出られない

Protecting SSH Keys with macOS Secure Enclave

macOSのSecure EnclaveでSSH鍵を守る——鍵はハードウェアから出られない

SSH秘密鍵をファイルではなくSecure Enclaveに保存するネイティブな方法を試した記録。sc_authで非エクスポート鍵を作成し、SSH_SK_PROVIDERを設定、Touch IDで署名を承認する。鍵は抽出不能で、使用のたびに生体認証が入る。ただしTouch IDのダイアログが「ctccardtoken needs to authenticate」と無骨で、筆者は美しさの面で納得できずSecretiveなど別解を検討中。

Touch IDダイアログが「SSHが鍵を使おうとしています」のような親切な文言ではなく「ctccardtoken needs to authenticate to continue」と表示されるのが気に入らない。
  1. database64128

    このようなセキュリティ機能は、機能しなくなるときまで機能する。

    macOSにWireGuardをインストールしたとき、秘密鍵をシステムキーチェーンに保存してくれることに気づいて嬉しかった。秘密鍵にアクセスするにはTouch IDが必要だ。

    そしてある日、システムアップグレードの後、WireGuardアプリが起動時にクラッシュした:

    [APP] Unable to open config from keychain: -25300

    その後、アプリはすべてのプロファイルを「孤児」であるとして削除した。どうやら「キーチェーンの一貫性」のためらしい[0]。

    それ以来、私はテキストエディタでWireGuardの設定ファイルを編集し、アプリにインポートするだけにしている。このバグは今日まで存在している[1]。

    [0] https://github.com/WireGuard/wireguard-apple/commit/dfb685f2...

    [1] https://www.reddit.com/r/WireGuard/comments/wyt828/osx_wireg...

  2. jwr

    何年も前に、自分が今使っているマシンのベンダーに依存しないハードウェアデバイスで鍵を保護したいと決めた。バックアップ鍵も持ちたいし、さまざまな物理的な場所に自由に移動させたい。必要なら世界中どこへでもバックアップを送ってもらいたい。

    これらの要件を満たす唯一のソリューションがYubiKeyだったので、それを使うことにした。過去10年ほど使っているが、このソリューションにはとても満足している。YubiKeyに保存したRSA鍵をGPGとSSHで同時に使えるようにする方法については、https://github.com/drduh/YubiKey-Guide を参照してほしい。

  3. mavam

    エージェントによる開発の根本的な問題の一つは、セキュアエンクレーブの鍵にアクセスするには人間の存在が必要だということだ。ヘッドレスで実行していてログインしていない場合、Secretive(他は知らない)はエンクレーブにアクセスできない。たとえ「通知」だけを選んで「touchid」を選んでいなくてもだ。

    だからこそ、このアプローチが確実にスケールするとは懐疑的だ。今は依存しているけれど。(そう、PATを使えば解決するが、今のところエンクレーブモデルを維持したいのだ。)代わりに私がやったのは、SSH認証ソケットを設定してエージェント転送を行う小さなデーモンを書くことだ。これはラップトップを持って旅行しているときには機能する…が、まだ携帯電話からは機能しない。

    例:

    Laptop Remote Mac

    ┌─────────────────────┐ ┌──────────────────────────┐

    │ Secretive │ │ ssh / git commit -S │

    │ (Secure Enclave) │ │ │ │

    │ ▲ │ ForwardAgent │ ▼ │

    │ └── ssh ─────┼─────────────────►│ ~/.ssh/agent.sock │

    │ │ │ (stable proxy) │

    └─────────────────────┘ │ │ │ │

    │ ▼ ▼ │

    │ forwarded local │

    │ laptop Secretive │ […]

  4. LeBit

    この記事は誤った前提から始まっている。

    著者は、鍵がファイルシステム上に置かれ、悪意のある者に奪われる準備ができているという考えが気に入らないと言っている。

    だからこそ、パスフレーズで保護すべきなのだ。

    ssh-agentを使って鍵をメモリに保存し、利便性のためにパスフレーズをキーチェーンに保存できる。macOSのOpenSSHにはそのためのUseKeychain設定ディレクティブがある。

    私自身はYubiKey/FIDO2を使っているが、それは秘密鍵をファイルシステム上で保護できないからではない。

  5. flexorium

    私は何年もSecretiveの満足なユーザーで、Gitコミット署名にも使っている(対話ありの別鍵になるが、プル/プッシュには使わない)。GitHub.comにはこのトレードオフが理想的だと思っているし、サーバー用には別の設定の鍵を使っている。

    平文のSSH鍵は、私たちの開発者エンドポイント秘密検出が最初に焦点を当てたものの一つだった[0]。その後、bagelをライブラリとして開発者エンドポイント保護に組み込んだ[1]。

    [0] https://boostsecurityio.github.io/bagel/

    [1] https://boostsecurityio.github.io/dazio/docs/install/

  6. jen729w

    私はこれに1Passwordの`op`を使っているが、例外を設けている:開発環境の鍵だ。

    指紋認証に疲れてきたことに気づいた。開発サーバーが開発用Supabaseに接続するたびに指紋認証が必要だろうか?いや。それは想定内でリスクはゼロだ。そこにデータはない。

    悪意のあるリクエストを私が自動承認してしまうのではないかと心配した。1日に20回もリクエストを見ると、筋肉記憶がセンサーに手を伸ばしてしまう。

    そこで、サービスアカウント[0]が読める別の1Passwordボールトを用意した。そのトークンは環境変数OP_SERVICE_ACCOUNT_TOKENとして設定しており、`op`ツールが理解する。

    また、Claudeが私に尋ねずにアクセスできるようにしたい「AIセーフ」な鍵のボールトにもアクセスできる。

    これで、これらのリクエストは目に見えずに機能する。そして指紋認証のポップアップが表示されたときは異常なので、習慣で自動承認することはない。

    また、別のボールトに「_One-day keys」というアイテムを置いている。(アンダースコアはリストの先頭に押し上げてアクセスしやすくするためだけだ。)

    本番用の鍵が入っていて、ほとんどが読み取り専用に制限されている。必要なら、それをオープンなボールトに移動する。Claudeはこのアイテムを知っていて、やるべきことが終わったら元に戻すように私に促す指示を持っている。

    [0]: https://www.1password.dev/service-accounts/get-started

  7. dylanger

    TKeyをチェックしてみるといい(https://www.tillitis.se/products/tkey/)

    実質的にYubiKeyのオープンソース版で、ハードウェア自体がすべてオープンソースで、ed25519 SSH鍵を非常によく扱う。

    inb4「同じものではない」と言われるだろうが、わかっている。TKeyチームのやっていることは本当に好きだ。

  8. gsliepen

    Secure EnclaveやTPMなどのセキュリティ機能は、残念ながら文書化がひどく不十分で、機能させるには多くのハードルを飛び越える必要があり、少しでも間違えると完全にロックアウトされるか、望んだ保護が得られない。これらの技術を使いやすくする、もっと良い方法があるはずだ…

この日のほかの記事

2026-11-11