🔑

Secretiveを使って簡単にGitの認証/署名鍵を Secure Enclave に保管する [macOS]

に公開

昨今のサプライチェーン攻撃の増加もあり、Gitのコミットに署名するのはかなり基本的なセキュリティ上のベストプラクティスとなっていますが、問題はこの署名を行う秘密鍵をどこに保管するかです。

その気になればパスワード保護されていないSSH鍵で署名を行うなんてこともできますが、悪意のあるプログラムが秘密鍵を読み取ってしまえば過去に行われた署名全てが無意味なものとなってしまいます。といってcommitpushの度に安全な長さのパスワードを打ち込むようでは、あまりにも煩雑で開発のモチベーションも下がってしまいます。

1PasswordなどのパスワードマネージャーをSSHエージェントとして動作させ署名/認証を行う方法もありますが、無駄に同期される分リスクが高まる上に、有償プランでないと使用できないなどの制限が伴います。

そこで役に立つのがSecretiveです。
https://github.com/maxgoedjen/secretive

TL;DR

Secretiveをインストールして画面の指示に従い環境変数SSH_AUTH_SOCKを設定 + 鍵を生成した上で、以下の設定を適当なエディターで追加

~/.gitconfig

[gpg]
	format = ssh
[commit]
	gpgsign = true

[user]
	name = <name>
	email = <email>
        # >>> アプリ内で表示されてるものではなく、 *環境変数適用後に ssh-add -L で取得した* 公開鍵 <<<
        # "ecdsa-sha2-nistp256 XXXX" から始まり、鍵の名前ではなく "ecdsa-sha2-nistp256" で終わる文字列になるはず
	signingKey = "key::[公開鍵]"

[gpg "ssh"]
	defaultKeyCommand = ssh-add -L

~/.ssh/config

Host github.com
        IdentityAgent /Users/[ユーザー名]/Library/Containers/com.maxgoedjen.Secretive.SecretAgent/Data/socket.ssh

ハマりポイント

  • .gitconfigで指定するsigningKeyアプリ内で見れる公開鍵ではなく、ssh-add -Lして取得したものに、key::を頭につけたものを指定する
    • アプリのセットアップで指示される環境変数適用後に実行しないと表示されないことに注意

長い説明

一般的にSSHの秘密鍵はディスク上に暗号化して保存されます。commitやpushなどで署名を要求する度に、sshエージェントがこれを復号化し要求された作業を行っている訳ですが、秘密鍵がそもそも暗号化されていない/鍵のパスワードが漏洩した場合や、sshエージェントやOS自体に脆弱性があった場合、CPUに対するサイドチャネル攻撃の存在などを考えると漏洩するリスクが付き纏います。

SecretiveはmacOS環境に搭載されている Secure Enclave に鍵を保管することでこの問題を大幅に緩和します。Secure EnclaveとはTEE(高信頼実行環境)の一種[要出典]で、普段作業を行なっているメインOS(ここではmacOS)とは独立して動作します。
TEE自体はApple端末固有のものではなく、近年のほぼ全てのモバイル端末(TrustZone)やWindows PC(Intel TXT, SGX / AMD PSP)にも似たような環境が備わっています。

Secure Enclave に保管されている秘密鍵にメインOSからアクセスされることはありません。
Secure Enclave が使用するコアは分離されている上に、メモリはメインOSのCPUからは見れない(Enclave側の鍵で暗号化される)ため、メインOSに対するサイドチャネル攻撃からも守られます。
署名など秘密鍵が必要な作業を要求されると、Secretiveの常駐エージェントを介して要求がSecure Enclaveに転送され、Secure Enclave内のみで秘密鍵が必要な処理が行われます。

また Secure Enclave は物理的な攻撃に対する耐性も持っている上に、Apple Silicon を搭載するデバイスではSoCに埋め込まれているため、デバイスが物理的に盗難されるなどしても安全性が保たれます。(もちろん絶対に安全というものはないので、盗まれないに越したことはありません)

Usage

GUIアプリなのでそこまで操作で迷うことはないと思います。操作実行時にTouchIDを要求するか鍵の生成時に聞かれますが、TouchIDを使える環境の場合はとりあえず要求する設定にしといた方が良いと思います。

ちなみにTouchIDの要求を無効にしても通知は来ます。

devcontainerとの併用

VSCodeの場合、上記の設定さえやっておけば自動的にエージェントを転送してコンテナ内でも鍵を使えるようにしてくれます。

その他制限事項

  • 当然ですが鍵はSecure Enclaveを離れることはないため、鍵を他の端末で使うことはできません。(GitHubはSSH鍵を複数設定できるので、Git関係で使用する場合はこの制限はほぼ問題にならないはず)
  • Secure Enclaveの仕様上、鍵は NIST P-256 CE(楕円曲線)鍵しか使用できません。この制限も特殊な環境でない限りはそこまで問題にならないと思います。

Discussion