PGP 主鍵を交換した話
先日 PGP 主鍵を交換しました.運用的にややこしいところがあったのでメモ代わりに書いておきます. 思い出しながら書いているので間違ってたらごめんなさい.
運用・利用スタイル
私は PGP を普段以下のような用途で使っています.
- Git コミット署名
- SSH チャレンジレスポンス認証
- (Email の署名・暗号化)
- (その他メッセージ等の署名・暗号化)
公開鍵は公開鍵サーバや Keybase などで公開しています. 秘密鍵は主鍵・副鍵共にローカル PC 上で作成し,どちらも Yubikey に焼いて普段は Yubikey 上で認証・署名・暗号化・復号等を行っています.
今までの鍵は色々いじくり回していたり管理がずさんだったりしたことや,主鍵の期限が今年 12 月に迫っていることから,主鍵を交換しました.
交換後は秘密鍵のバックアップを用意した適当なメディアに焼き,副鍵の秘密鍵のみを Yubikey に焼いて,主鍵は副鍵の生成や失効など以外では基本的に使用しない・マウントしない・物理的に触らないようにします. また,物理インターフェースの互換性や可用性の観点から,Yubikey を複数本利用します.
交換方法
主鍵・副鍵の作成
Yubikey を使う場合,鍵をローカルマシンで作成してから Yubikey に移す方法と Yubikey 上で作成しそのまま利用する方法があります. Yubikey に入れた秘密鍵は二度と取り出せないため,バックアップのため今回は前者で作成しました.
主鍵は Sign, Certify ができるものを NIST P-521 で作成し,副鍵は Encryption 鍵を NIST P-521 で,Sign, Authentication 鍵を Ed25519 で計 2 本作成しました.アルゴはあまり詳しくないのでとりあえず楕円ということ以外はこだわりはありません.
作成は信頼しているローカルマシンのターミナル上で,GPG を使って行いました.
秘密鍵のバックアップ作成
秘密鍵のバックアップは専用のメディアを用意し,そこに ASCII の鍵を保存することで行いました. 具体的には,以下のもののバックアップをとります.
- 主鍵・副鍵秘密鍵
- 副鍵のみの秘密鍵 (あとで Yubikey に焼きやすいように)
- 失効証明書
これらは絶対に漏洩してはならず,漏洩したか漏洩の疑いがある場合には主鍵を失効しなければなりません.
今後の操作ではオペミス防止のため,バックアップの秘密鍵に触るコマンドを叩くとき以外はバックアップメディア自体をアンマウントし物理的に接続を解除します.
鍵の署名
新しい鍵と古い鍵のエンティティの一貫性を担保するため,古い鍵の秘密鍵で新しい鍵の公開鍵に署名します.
公開鍵の公開
タイミングに迷うのですが,もうこの時点で公開してしまいました. 今回は速くて使い勝手のよい keys.openpgp.org を利用しました.
Key Transition Statement の作成
今回の主鍵交換が私の意思によって行われたものであることを示すため,Key Transition Statement を作成します. これは,「主鍵を交換したのでみんな確認して,署名したい人は署名してね」という文書を作成し,それに古い秘密鍵と新しい秘密鍵の両方で署名をすることで,他の人に秘密鍵のエンティティの一貫性を知らせるものです. 元は作成したものをメールで送信などしていたようですが,私は GitHub 上で公開しました. 私の Key Transition Statement はこちらから確認できます.
秘密鍵をローカルマシンから消去
このあと Yubikey に秘密鍵を焼くわけですが,そのまま焼くと主鍵も一緒に焼かれてしまうので,先に秘密鍵をローカルマシンから消します.また,漏れて困るものは忘れないうちに先に削除します.
消す前に,公開鍵 (ASCII) と SSH 用の公開鍵 (ASCII) を出力して適当なところに置いておきます.これは見せびらかす鍵なのでどこにおいてもいいです.
ここからは消去になります.
まず,gpg
コマンドで GPG のキーリングから秘密鍵を消します.
その後,~/.gnupg/private-keys-v1.d
以下にある秘密鍵と ~/.gnupg/openpgp-revocs.d
以下にある失効証明書を消去します.
gpg
コマンドだけではローカルマシンにある秘密鍵の実体は消去されないので注意が必要です.
Yubikey に秘密鍵を焼く - 1 本目
ここまではネットを探せばわかりやすい記事がたくさん落ちているのですが,ここからはあまり落ちていませんでした. なお,一応古い秘密鍵のバックアップがあるという前提で書いています.
まず準備として,先ほど作成したバックアップから副鍵のみの秘密鍵を GPG キーリングに import します.
import したら gpg -K
を実行し,主鍵秘密鍵を表す sec
の隣に #
がついていること,副鍵秘密鍵を表す ssb
の隣に >
がついていることを確認します.
#
は秘密鍵そのものが import されていないこと,>
は秘密鍵そのものが import されていることを示します.
確認できたら, Yubikey をローカルマシンに接続し,gpg --card-edit
から admin
factory-reset
を実行することで,Yubikey に格納されている古い鍵を消します.
次に,Yubikey に新しい秘密鍵を焼きます.gpg --edit-key '新しい主鍵指紋'
から key n
(n は副鍵の番号) で焼きたい鍵を選択し,keytocard
で Yubikey に焼きます.
焼く際にどのスロットに焼くかきかれますが,必ず使いたい usage のスロットに焼くようにしてください.
たとえば一つの副鍵に Sign と Authentication の二つの usage を持たせている場合,同じ鍵を Sign と Authentication のそれぞれのスロットに焼きます.
副鍵が複数ある場合 (大抵はそうでしょうが) 焼きたい副鍵の数だけこれを繰り返します.
なお,繰り返すときには焼く前に key 前に焼いた鍵の番号
で既に焼いた鍵の選択を外します.
終わったら save
で抜けます,
なお,この時に quit
して保存せず終了としても構いません.
save
するかどうかにかかわらず keytocard
を実行した時点で Yubikey に鍵が焼かれています.
save
した場合にはローカルマシンから焼いた秘密鍵が消えますが,save
せず quit
した場合にはローカルマシン上に秘密鍵が残ります.
Yubikey に秘密鍵を焼く - 2 本目以降
2 本目以降に鍵を焼くときには,環境をクリーンアップしなければなりません.
これは,一度 keytocard
をすると GPG が「この秘密鍵はこの番号のスマートカード (Yubikey) に焼かれている」と覚えてしまい,2 本目以降焼けなくなるからです.
そのため,前述「秘密鍵をローカルマシンから削除」で行ったのと同じ手順で秘密鍵情報をローカルマシンから一掃します.
その後は,1 本目と同じやり方で焼きます. すべて焼き終わったら忘れずローカルマシンから秘密鍵情報をすべて消し去ります.
SSH で使えるようにする
Yubikey + PGP で SSH チャレンジレスポンス認証をしている場合,新しい公開鍵をリモートサーバの ~/.ssh/authorized_keys
において今までどおりに PC に Yubikey を刺して SSH 接続しようとしても失敗します.
これは,GPG-agent が Yubikey で使っている鍵の Keygrip を保存しており,刺した Yubikey が GPG-agent の想定している鍵と違う鍵を持っていた場合認証 (チャレンジへの署名) が実行されないからです.
この場合,ssh-add -l
ないしは ssh-add -L
コマンドを実行すると,古い鍵が表示されているはずです.
そのため,GPG-agent が覚えている Keygrip を更新します.
~/.gnupg/sshcontrol
をテキストエディタで開き,今ある Keygrip を消し,新しい Authentication 用副鍵の Keygrip を入力し保存します.
これはやり方があっているかかなり不安なのですが,一応私の環境では動作しました.
これで Yubikey を刺すだけで SSH できるようになったはずです.
Git で使えるようにする
Git のコミット署名に PGP を利用している場合,多くの人は ~/.gitconfig
にこんな設定を書いていると思います.
[user] signingkey = (署名鍵指紋)
この署名鍵の指紋も変更する必要があります.
今度の鍵はもうちょっとまともに運用するように心がけたいです. 皆さんも PGP で楽しくセキュアでトラストフルな生活を〜