概要
GitHubではMergeコミットなどで

といったマークを見ます。これは署名されたcommitを示すものなのですが、
- なぜ必要なのか
- どうやったら署名できるのか
を今回説明します。
環境
- macOS 10.14.5 Mojave
- gpg 2.2.10
なぜ署名が必要か?
gitのコミットは
commit 91e8e61ee6601576e358201315b6624181529879 (HEAD -> refactor-chain, origin/refactor-chain)
Author: Junpei Tsuji <junpei.tsuji.ams@gmail.com>
Date: Sun Jul 14 11:42:29 2019 +0900
Fixed a bug
のようにAuther名やEmailが付きますが、これらは自分で設定可能です。
ということは他人の名前やEmailを設定してcommitすることもできるため、なりすましが可能です。
GitHub上ではcommitにそういったなりすましではないことを保証するための仕組みとして署名をしたらVerifiedマークが付くようになってます。
GPG Suite
GPG周りの設定が手間にならないよう、 GPG Suite をインストールします。
インストール

ただし注意としてGPG Mailは有料機能で1ヶ月トライアルとなっているので、カスタマイズで外します。

チェックボックスをOFFにしてください。

gpg-agent.confの修正
~/.gnupg/gpg-agent.confに以下を追記します。
pinentry-program /usr/local/MacGPG2/libexec/pinentry-mac.app/Contents/MacOS/pinentry-mac
pinentryはパスフレーズ等の入力ダイアログ群で対話的に行うためのツールです。
GPG鍵を生成
それでは鍵を生成していきます。
Generating a new GPG key - GitHub Help に沿って進めます。
$ gpg --full-generate-key
鍵の種類
鍵の種類の選択です。1のRSAで。
ご希望の鍵の種類を選択してください: (1) RSA と RSA (デフォルト) (2) DSA と Elgamal (3) DSA (署名のみ) (4) RSA (署名のみ) あなたの選択は? 1
鍵長
次に鍵長の指定です。
GitHubは4096ビットを推奨してるので4096で。
RSA 鍵は 1024 から 4096 ビットの長さで可能です。 鍵長は? (2048) 4096
鍵の有効期限
最後は鍵の有効期限です。
GitHubでも無期限でOKとあるのでそのままEnter。
鍵の有効期限を指定してください。
0 = 鍵は無期限
<n> = 鍵は n 日間で期限切れ
<n>w = 鍵は n 週間で期限切れ
<n>m = 鍵は n か月間で期限切れ
<n>y = 鍵は n 年間で期限切れ
鍵の有効期間は? (0)
名前、メールアドレス、コメント
確認画面でyを押すと、名前、メールアドレス、コメントを聞かれます。
Note: When asked to enter your email address, ensure that you enter the verified email address for your GitHub account. To keep your email address private, use your GitHub-provided no-reply email address.
とあるようにメールアドレスはGitHubに登録してあるメールアドレスを入力します。コメントは任意です。分かりやすいようGitHubとしておきます。
GnuPGはあなたの鍵を識別するためにユーザIDを構成する必要があります。
本名: Junpei Tsuji
電子メール・アドレス: junpei.tsuji.ams@gmail.com
コメント: GitHub
次のユーザIDを選択しました:
"Junpei Tsuji (GitHub) <junpei.tsuji.ams@gmail.com>"
鍵のパスフレーズ
次は鍵のパスフレーズを入力します。

エントロピーの供給
するとセキュリティのため十分なエントロピープールがほしいと言われます。
たくさんのランダム・バイトの生成が必要です。キーボードを打つ、マウスを動か す、ディスクにアクセスするなどの他の操作を素数生成の間に行うことで、乱数生 成器に十分なエントロピーを供給する機会を与えることができます。
で説明したやつですね。既に十分あればすぐに終わりますし、なければ指示通りマウスを動かしたりしてください。
完了
以上で完了です。
gpg: /Users/jun06t/.gnupg/trustdb.gpg: 信用データベースができました
gpg: 鍵XXXXを究極的に信用するよう記録しました
gpg: ディレクトリ'/Users/jun06t/.gnupg/openpgp-revocs.d'が作成されました
gpg: 失効証明書を '/Users/jun06t/.gnupg/openpgp-revocs.d/YYYY.rev' に保管しました。
公開鍵と秘密鍵を作成し、署名しました。
pub rsa4096 2019-07-14 [SC]
YYYY
uid Junpei Tsuji (GitHub) <junpei.tsuji.ams@gmail.com>
sub rsa4096 2019-07-14 [E]
GitHub側の設定
GPG公開鍵の生成
先程のXXXXが秘密鍵のIDなので、それを使って公開鍵を生成します。
忘れてしまったら以下のコマンドで表示できます。
$ gpg --list-secret-keys --keyid-format LONG
gpg: 信用データベースの検査
gpg: marginals needed: 3 completes needed: 1 trust model: pgp
gpg: 深さ: 0 有効性: 1 署名: 0 信用: 0-, 0q, 0n, 0m, 0f, 1u
/Users/jun06t/.gnupg/pubring.kbx
--------------------------------
sec rsa4096/XXXX 2019-07-14 [SC]
YYYY
uid [ 究極 ] Junpei Tsuji (GitHub) <junpei.tsuji.ams@gmail.com>
ssb rsa4096/ZZZZ 2019-07-14 [E]
以下で公開鍵を生成可能です。
$ gpg --armor --export XXXX -----BEGIN PGP PUBLIC KEY BLOCK----- ... -----END PGP PUBLIC KEY BLOCK-----
この公開鍵をコピーしておいてください。
GPG公開鍵をGitHubに登録
https://github.com/settings/keys で登録します。

右上のボタンをクリックし、

先程の公開鍵を入力。

するとこのようにGitHubで登録が完了します。
他人のメールアドレスでも作れちゃうのでは?
本人確認のための署名であるはずですが、これまでは全て自分で設定していました。
であれば他人の名前やメールアドレスを騙ってなりすましできてしまうのでは?と思います。
しかしGitHub上の悪意あるユーザのアカウントでは、他人のメールアドレスはVerifiedできていない(=メールアドレス確認ができない)ので、以下のように表示されます。

今回検証のためtaro.yamada@gmail.comのアカウントのGPG鍵を用意しましたが、commitしてもverifyマークはつかない事が分かります。

ローカル開発マシンの設定
gitconfig
gitで署名ができるように設定を行います。
先程の鍵IDをconfigに設定しておきます。
$ git config --global user.signingkey XXXX
また、GPGプログラムの指定をします。
$ git config --global gpg.program /usr/local/MacGPG2/bin/gpg2
.gitconfigは以下のようになるはずです。
[user] name = Junpei Tsuji email = junpei.tsuji.ams@gmail.com signingkey = XXXX [gpg] program = /usr/local/MacGPG2/bin/gpg2
Commitを署名する
commit時に-Sを付けてあげます。
$ git commit -S -m "Fixed a bug"
すると以下のようにGPG鍵のパスフレーズ入力を求められます。

チェックボックスでkeychainに保存しておけば最初だけで済みます。
動作検証
GitHubにpushしてcommitを見てみると

このようにverifiedマークが付くようになりました。