GitHubにPGP鍵を登録して署名つきcommitを作成してみた

2020.04.28

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

GitではPGP鍵を利用したCommitへの署名ができることを以前から知っていましたが, 下記記事を拝見して簡単に設定できることを知ったのでPGP鍵の生成から設定までやろうと思いました.

また, とあるプロジェクトのCode Ownerになったため, リポジトリへのCommitに対して署名をすることで偽装を防げる方が良いのではないかと感じたことにも起因しています.

本記事では, 下記4点について実施したことをまとめます.

  • macOSでのPGP鍵の生成
  • Gitでの署名つきCommitの実行
  • GitHubへの公開鍵の登録
  • 他のPCへの秘密鍵のインポート

macOSでのPGP鍵の生成

まずは必要なツールをインストールします. PGP鍵を生成するためのGnuPGとパスフレーズ入力に利用するPinentryをインストールします.
インストールが完了したらGnuPGのバージョンを確認して, 2以降であることを確認してください.

$ brew install gpg pinentry-mac

$ gpg --version
gpg (GnuPG) 2.2.20
libgcrypt 1.8.5
Copyright (C) 2020 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

ツールのインストールが完了したら, GnuPGの設定を行います.
下記2コマンドを実行して, GnuPGで利用するPinentryのパスを指定します.

$ echo "pinentry-program /usr/local/bin/pinentry-mac" > ~/.gnupg/gpg-agent.conf
$ gpgconf --kill gpg-agent

PGP鍵の生成

ツールのインストールが完了したら次に, PGP鍵を生成します.
一部出力を端折って, 対話的に入力を求められる部分のみ記載します.

Please select what kind of key you want:
   (1) RSA and RSA (default)
   (2) DSA and Elgamal
   (3) DSA (sign only)
   (4) RSA (sign only)
  (14) Existing key from card
Your selection?                                   # Enterを押してデフォルトを利用する

RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (2048) 4096             # 4096 bitsを入力する

Please specify how long the key should be valid.
         0 = key does not expire
      <n>  = key expires in n days
      <n>w = key expires in n weeks
      <n>m = key expires in n months
      <n>y = key expires in n years
Key is valid for? (0)                             # Enterを押してデフォルトを利用する
Is this correct? (y/N) y                          # y を入力する

ここまでは基本的に同じ入力で問題ありません.
プロンプト的には続きからになりますが, 「Real name」と「Email address」、「Comment」、「Passphrase」はご自身のものを入力してください.
また登録するメールアドレスはGitHubにも登録しているメールアドレスである必要があるので注意してください.
最後に, 「o」を入力しましょう.

GnuPG needs to construct a user ID to identify your key.

Real name: example
Email address: example@example.com
Comment: example PGP Key          
You selected this USER-ID:
    "example (example PGP Key) <example@example.com>"

Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? o

入力が終わると, 下記画像のようにPinentry経由でパスフレーズの入力を求められるのでパスフレーズを生成して入力しましょう.

これでGnuPGとの対話が完了します.
最後に秘密鍵と公開鍵を生成します. この2つの鍵については後ほど利用します.

# 秘密鍵の生成
$ gpg --export-secret-keys XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX > privkey.gpg

# 公開鍵の生成
$ gpg --armor --export XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX > pubkey.gpg

Gitでの署名つきCommitの実行

次にGitでPGPを利用するように設定をしていきます.
私の環境では, GitHub以外にCommitすることがないので, 全てのCommitに対して署名をするように指定します.

$ git config --global gpg.program "/usr/local/bin/gpg"
$ git config --global user.signingkey "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
$ git config --global commit.gpgsign true

この時の設定ではパスフレーズの入力などは求められませんが, Commitを実際に行う際にパスフレーズの入力を求められます.

MacOSの場合は下記のような画面が出るのでパスフレーズを入力しましょう. またキーチェーンに登録することで次回以降の入力の手間を省くことができます.
これでクライアント側の設定は完了しました.

GitHubに公開鍵を登録する

最後にGitHub側でCommitが署名されているかを検証できるように公開鍵を登録します.
SSH and GPG keysから「New GPG Key」を選択して公開鍵を貼り付けます.
これでGitHub側で署名つきCommitに関して検証ができるようになります.
公開鍵登録後にpushした署名つきCommitについては下記のように「Verified」と表示されます.

ここまでがGitHubにPGP鍵を登録して署名つきcommitを作成する方法です.

秘密鍵を他の端末にインポートする

PCを2台持っていたり, PCを移行する際に既存のPGP鍵を破棄して新たに作成する... といった方法より既存のPGP鍵を利用する方を好む場合もあります.
特に前者は私が想定しているユースケースであり, GnuPGではそれが実現可能だったので記載していきます.

下記の作業を行う前に, GnuPGとPinentryのインストール, GnuPGの設定, Gitの設定を新規端末でも行ってください.
また既存端末で払い出した, 「private.gpg」を新規端末にコピーしてください.

ここまでの準備が終わったら, 下記コマンドを実行し, パスフレーズを入力することでPGP鍵のインポートが終了します.

$ gpg --import private.key

gpg --import privkey.gpg
gpg: /Users/xxxxx/.gnupg/trustdb.gpg: trustdb created
gpg: key XXXXXXXXXXXXXXXX: public key "example <example@example.com>" imported
gpg: key XXXXXXXXXXXXXXXX: secret key imported
gpg: Total number processed: 1
gpg:               imported: 1
gpg:       secret keys read: 1
gpg:   secret keys imported: 1

これで秘密鍵のインポートが完了し, 新規端末でも署名つきCommitが可能になります.

さいごに

PGPの生成からGitへの登録, GitHubへの公開鍵の登録まで非常にシンプルに行うことができてかつ, Commitの偽装を防ぐことができるので良い仕組みだと感じました.
みなさまのお役に立てたら幸いです.

参考資料