GPG鍵を作って運用し、Git(hub)やMercurialで自分が書いたコードに署名をする

自分が書いたコードに署名をしておくことはプログラマの常識であり基本動作です(かくいう私もメールは署名してないけど…)。なので私も一人前のプログラマになるべく、自分が書いたコードに署名をするようにしてみた。

GPG 鍵を作ったり準備したり

GnuPGのインストール@MacOS

$ sudo port install gnupg

鍵をつくります。有効期限は2年間。もし秘密鍵が漏れた場合でも、2年経てばほとぼりが冷める。

$ gpg --gen-key
gpg (GnuPG) 1.4.20; Copyright (C) 2015 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

ご希望の鍵の種類を選択してください:
   (1) RSA と RSA (デフォルト)
   (2) DSA と Elgamal
   (3) DSA (署名のみ)
   (4) RSA (署名のみ)
選択は? 
RSA 鍵は 1024 から 4096 ビットの長さで可能です。
鍵長は? (2048) 4096
要求された鍵長は4096ビット
(中略)
鍵の有効期間は? (0)2y
鍵は木  7/12 00:41:58 2018 JSTで期限切れとなります
これで正しいですか? (y/N) y

あなたの鍵を同定するためにユーザIDが必要です。
(中略)
gpg: 鍵8CD45203を究極的に信用するよう記録しました
公開鍵と秘密鍵を作成し、署名しました。

gpg: 信用データベースの検査
gpg: 最小の「ある程度の信用」3、最小の「全面的信用」1、PGP信用モデル
gpg: 深さ: 0  有効性:   2  署名:   0  信用: 0-, 0q, 0n, 0m, 0f, 2u
gpg: 次回の信用データベース検査は、2018-07-11です
pub   4096R/8CD45203 2016-07-11 [有効期限: 2018-07-11]
 フィンガー・プリント = FF7E B3FF 4AEE ADEA 764D  2F33 BD95 145F 8CD4 5203
uid                  Kota UENISHI (h) <kuenishi@gmail.com>
sub   4096R/B99B64AE 2016-07-11 [有効期限: 2018-07-11]

kuenishi@mineva.local> $ gpg --list-keys
/Users/kuenishi/.gnupg/pubring.gpg
----------------------------------
pub   4096R/8CD45203 2016-07-11 [有効期限: 2018-07-11]
uid                  Kota UENISHI (h) <kuenishi@gmail.com>
sub   4096R/B99B64AE 2016-07-11 [有効期限: 2018-07-11]

鍵をバックアップして保存しておく。失効証明書とあわせて、この3つのファイルがマスターになるらしい。

$ gpg --export-secret-keys --armor kuenishi@gmail.com > secret-key.backup
$ gpg --export -armor kuenishi@gmail.com > public-key.backup

インポートは簡単に "gpg --import (secret|public)-key.backup" とやってよいようだ (追記: インポート後に鍵の信頼度を設定しないとずっと信用できないと言われ続ける。方法はオマケ参照)。

GitHub にGPG鍵を登録する

これを登録しておくとGithubで Verified と出てかっこいい。

$ gpg --list-secret-keys --keyid-format LONG
/Users/kuenishi/.gnupg/secring.gpg
----------------------------------
sec   4096R/BD95145F8CD45203 2016-07-11 [有効期限: 2018-07-11]
uid                          Kota UENISHI (h) <kuenishi@gmail.com>
ssb   4096R/883A16F6B99B64AE 2016-07-11
$ $ gpg --armor --export BD95145F8CD45203
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v1

mQINBFeDvmgBEADkjeoWVk9AbsOeSdCxHQGtyHEiFvXn+7dEGvw3yqs7IHk4dYil
GbcTp/CcWxk2QnrG3UXleohARh+jEx5MDMfGAf3hOGCtHrQrOd4RfvEtShgRf5kP
...
-----END PGP PUBLIC KEY BLOCK-----

と出る。これをGithubに登録する。具体的には "Settings > SSH and GPG keys" のメニューから登録する。こんな感じ。

f:id:kuenishi:20160712010215p:plain

Git にGPG鍵を設定する

これも簡単。

$ gpg --list-keys
/Users/kuenishi/.gnupg/pubring.gpg
pub   4096R/8CD45203 2016-07-11 [有効期限: 2018-07-11]
uid                  Kota UENISHI (h) <kuenishi@gmail.com>
sub   4096R/B99B64AE 2016-07-11 [有効期限: 2018-07-11]

$ git config --global user.signingkey 8CD45203 
$ git config --get user.signingkey
8CD45203

署名つきコミットやタグを作る

このあたりはGitの公式ドキュメントが詳しい。まずは署名つきのコミットをつくる。 "-S" をつけると署名をGPGの設定に従ってつけてくれる。

$ emacs README.md
$ git add README.md
$ git commit -S -m "Fix docs"

次のユーザの秘密鍵のロックを解除するには
パスフレーズがいります:"Kota UENISHI (h) <kuenishi@gmail.com>"
4096ビットRSA鍵, ID 8CD45203作成日付は2016-07-11

[master 6f12b24] Fix docs    
 1 file changed, 3 insertions(+), 3 deletions(-)

コミットが署名されているかどうかは git-show で分かる。

$ git log --show-signature -1
commit 6f12b24585f997cdf405ef38e00392bfdf3f4193
gpg: 火  7/12 01:07:56 2016 JSTにRSA鍵ID 8CD45203で施された署名
gpg: "Kota UENISHI (h) <kuenishi@gmail.com>"からの正しい署名
Author: UENISHI Kota <kuenishi@gmail.com>
Date:   Tue Jul 12 01:07:56 2016 +0900

    Fix docs

普段使っている git-tag コマンドに "-s" オプションをつけることで、署名つきのタグを作ることもできる。署名は git-show で確認できる。

$ git tag -s 0.0.1 -m "First signed relase 0.0.1"

次のユーザの秘密鍵のロックを解除するには
パスフレーズがいります:"Kota UENISHI (h) <kuenishi@gmail.com>"
4096ビットRSA鍵, ID 8CD45203作成日付は2016-07-11

$ git show 0.0.1
tag 0.0.1
tag 0.0.1
Tagger: UENISHI Kota <kuenishi@gmail.com>
Date:   Tue Jul 12 01:11:34 2016 +0900

First signed relase 0.0.1
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1

iQIcBAABAgAGBQJXg8U2AAoJEL2VFF+M1FIDkeYQAOCOtjX2q5Ai+uq5/S+Rh0uE
K4xR4VlbUriPb376fweLNglct5dgSSxU151Auq36kWAiEKkEZR3mEdtYbMmEqEXV
Srx0+4b/Z3WFCh6A9B2mjdjMNBs3gGuQJvkGEAeseHBOOoM+jyxHtZFG4032HZgw
tag 0.0.1
Tagger: UENISHI Kota <kuenishi@gmail.com>
Date:   Tue Jul 12 01:11:34 2016 +0900

First signed relase 0.0.1
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1

iQIcBAABAgAGBQJXg8U2AAoJEL2VFF+M1FIDkeYQAOCOtjX2q5Ai+uq5/S+Rh0uE
K4xR4VlbUriPb376fweLNglct5dgSSxU151Auq36kWAiEKkEZR3mEdtYbMmEqEXV
Srx0+4b/Z3WFCh6A9B2mjdjMNBs3gGuQJvkGEAeseHBOOoM+jyxHtZFG4032HZgw
t2g1GS7BPIoas2azrKRWY9Jt4hCfEQ5TQpmbm9lbtbMDK9JRZ6mxkdoTyUdHM3c5
8chHTvXW+6yRbIEA3MKLzA+r/4crjLDOm/UqLpggRw3e0+mEpPeN40ifrq6MyBwy
82VBuAw/38qAsO2OXNeRwNbNPXPmTT4S/OQ09cAu7CjgHQ7/X6ZYb2/9w01BvAEn
5XdA4oaMeFq8/4W1W+jFSUBlrEM7YWEoE7ZPjLeln7iFND+mTfV2OU92ftOku0ou
IOP8l1/NzphLTJJR3nvqMzCzX+sONgeyfc8wT81yyOgAyR1uwgy9svyDHdEfvqM2
hulOuJ+HhzbuhLZ0rmXot+gXCGoAE7oXP4wFXHQ+NP1iTKP1flSHtXnFiUs19ikm
MspL75R29ATz7lAaWM1vv5AKivIy3Xsu7ngE69fnHa6R28frBPvfTbY+m2dxBiNd
I0npPtpAUS/FMQvZCFzACumZ5LdWCNx1uE7K2sUJv5zaMXTsTbB+XfMbvyOH0Hoe
jtP4uzxY324qTrj8gtxV
=AvrO
-----END PGP SIGNATURE-----

commit 6f12b24585f997cdf405ef38e00392bfdf3f4193
Author: UENISHI Kota <kuenishi@gmail.com>
Date:   Tue Jul 12 01:07:56 2016 +0900

    Fix docs

diff --git a/README.md b/README.md
index 19af36d..97490a4 100644
--- a/README.md
+++ b/README.md
@@ -1,11 +1,11 @@
(snip)

タグの確認は -v オプションだ。

$ git tag -v 0.0.1
object 6f12b24585f997cdf405ef38e00392bfdf3f4193
type commit
tag 0.0.1
tagger UENISHI Kota <kuenishi@gmail.com> 1468253494 +0900

First signed relase 0.0.1
gpg: 火  7/12 01:11:34 2016 JSTにRSA鍵ID 8CD45203で施された署名
gpg: "Kota UENISHI (h) <kuenishi@gmail.com>"からの正しい署名

これを git-push すると… こうなる

f:id:kuenishi:20160712011555p:plain

Verifyされた!これで私もVerified Engineerだ(??)

タグの方も無事にVerifyされている

f:id:kuenishi:20160712011709p:plain

Mercurial と Bitbucket

Mercurialには素晴らしい日本語ドキュメントがついており、使い方も簡単な ので*1、それに従うだけでよい。Mercurial は gpg というエクステンションが公式パッケージに含まれているので、これを有効化して設定するとよい。わたしの ~/.hgrc はこうなっている。レポジトリ毎に使い分けたい場合は .hg/hgrc を以下のように設定すればよいと思う。

username = UENISHI Kota <kuenishi@gmail.com>

[extensions]
hgext.gpg=

[gpg]
cmd=/opt/local/bin/gpg
key=8CD45203

署名するには hg-sign だ。tip の代わりに特定のリビジョンをつけてもいいと思う。

$ hg sign tip
signing 3116:3dacfa73a0f7

次のユーザの秘密鍵のロックを解除するには
パスフレーズがいります:"Kota UENISHI (h) <kuenishi@gmail.com>"
4096ビットRSA鍵, ID 8CD45203作成日付は2016-07-11
$ hg log -r 3117
changeset:   3117:d7d5cf15a1b3
tag:         tip
user:        UENISHI Kota <kuenishi@gmail.com>
date:        Tue Jul 12 01:22:52 2016 +0900
summary:     Added signature for changeset 3dacfa73a0f7

Mercurialの場合は、直前のコミットの署名を .hgsigs というファイルに追加した変更をコミットするという形での署名になる。

$ hg diff -r 3116
diff -r 3dacfa73a0f7 .hgsigs
--- a/.hgsigs   Mon Jul 11 23:25:41 2016 +0900
+++ b/.hgsigs   Tue Jul 12 01:25:36 2016 +0900
@@ -1,1 +1,2 @@
(snip)

署名の確認は、署名対象のコミットを引数にして hg-sigcheck を呼ぶ。

$ hg sigcheck 3116
3dacfa73a0f7 is signed by:
 Kota UENISHI (h) <kuenishi@gmail.com>

これをBitbucketに投稿してみたのだが、Bitbucketのコミットのページになんか出るということもなかったので、なんだかつまんなかった。

まとめ

  • GnuPGを使って鍵を作り、自分のコードに署名する方法をまとめた
  • Github は署名をサポートしている(Mercurial @ Bitbucket はイマイチ)
  • 署名はプログラマーの基本動作
  • できればメールも署名くらいはしたい

おまけ

Fingerprintも出しておこう!!

$ LANG=C gpg --fingerprint 8CD45203
pub   4096R/8CD45203 2016-07-11 [expires: 2018-07-11]
      Key fingerprint = FF7E B3FF 4AEE ADEA 764D  2F33 BD95 145F 8CD4 5203
uid                  Kota UENISHI (h) <kuenishi@gmail.com>
sub   4096R/B99B64AE 2016-07-11 [expires: 2018-07-11]

追加

鍵を公開鍵サーバーに登録する

$ gpg --keyserver pgp.nic.ad.jp --send-keys 382AF48A 
gpg: sending key 382AF48A to hkp server pgp.nic.ad.jp

鍵のバックアップ

$ gpg --export --armor kuenishi@gmail.com > gpg-public-key.backup
$ gpg --export-secret-keys --armor kuenishi@gmail.com  > gpg-secret-key.backup
$ gpg --gen-revoke kuenishi@gmail.com > gpg-revoke-key.backup

鍵をインポートする

$ gpg --import gpg-public-key.backup
$ gpg --allow-secret-key-import --import gpg-secret-key.backup

このままだと、インポートした鍵は信用されていないので、ローカルで信用度をつけておく

$ gpg --edit-key kuenishi@gmail.com
(snip)
> trust
pub  4096R/8CD45203  作成: 2016-07-11  有効期限: 2018-07-11  利用法: SC  
                     信用: 未知の     有効性: 未知の
sub  4096R/B99B64AE  作成: 2016-07-11  有効期限: 2018-07-11  利用法: E   
[  未知  ] (1). Kota UENISHI (h) <kuenishi@gmail.com>

他のユーザの鍵を正しく検証するために、このユーザの信用度を決めてください
(パスポートを見せてもらったり、他から得たフィンガー・プリントを検査したり、などなど)

  1 = 知らない、または何とも言えない
  2 = 信用し ない
  3 = まぁまぁ信用する
  4 = 充分に信用する
  5 = 究極的に信用する
  m = メーン・メニューに戻る

あなたの決定は? 5
本当にこの鍵を究極的に信用しますか? (y/N) y

pub  4096R/8CD45203  作成: 2016-07-11  有効期限: 2018-07-11  利用法: SC  
                     信用: 究極        有効性: 未知の
sub  4096R/B99B64AE  作成: 2016-07-11  有効期限: 2018-07-11  利用法: E   
[  未知  ] (1). Kota UENISHI (h) <kuenishi@gmail.com>
プログラムを再起動するまで、表示された鍵の有効性は正しくないかもしれない、
ということを念頭においてください。

gpg>quit

*1:ここは英語だけど…