githubで使うGPG鍵の作成

# GitHubでのGPG

gitではGPG(Gnu Private Guard)を用いて、commitやtagにsignすることができます。GitHubでは、このsignを用いて認証を行い、認証が成功したものに関しては、verifiedというマークを付与します。

GitHubでの認証にはweb of trustは用いられず、単にcontributerのうちの誰かと認証されることによってのみ、認証は成功とみなされます。

# 鍵の生成

まず、鍵を生成します。

```shell
gpg --full-gen-key
```

ただ待っていると時間がかかるので、[gpg --gen-keyが止まる件について](https://qiita.com/kanatatsu64/items/c6f612b34ec69809fbb6)を参考に、対策してください。

次に、生成した鍵を確認します。署名に使うのは、pub keyでもsub keyでも構いませんが、sub keyの方が安心でしょう。

```shell
gpg --list-keys --keyid-format short
#pub   rsa4096/C1356B8B 2019-01-28 [SC] [expires: 2020-01-28]
#      8E579C1DA2A96D755833A5B3A294B64FC3354B8B
#uid         [ultimate] Hoge Fuga <hoge@example.com>
#sub   rsa4096/A1279318 2019-01-28 [E] [expires: 2020-01-28]
```

上の場合、subkeyが署名に対応していない[*](#余談)ので、別のsubkeyを作ります。この時点で、subkeyが署名に対応している人は、[GitHubに登録](#githubに登録)まで飛ばして構いません。

```shell
gpg --edit-key C1356B8B  # pubkeyのID
gpg> addkey
gpg> save
```

addkeyを実行した時に、暗号の種類を聞かれますので、署名に対応したものを選んでください。

これを実行すると、新たなsubkeyが生成されます。

```shell
gpg --list-keys --keyid-format short
#pub   rsa4096/C1356B8B 2019-01-28 [SC] [expires: 2020-01-28]
#      8E579C1DA2A96D755833A5B3A294B64FC3354B8B
#uid         [ultimate] Hoge Fuga <hoge@example.com>
#sub   rsa4096/A1279318 2019-01-28 [E] [expires: 2020-01-28]
#sub   rsa2048/39D812AC 2019-01-28 [S] [expires: 2020-01-28]
```

今生成した鍵は、[S]と書いてあるので、ちゃんと署名に対応していますね。

# GitHubに登録

pub keyをGitHubに登録します。

鍵のIDはC1356B8Bです。この鍵の中身を見るには、

```shell
gpg --armor --export  C1356B8B  # pubkeyのID
```

とします。

この内容をクリップボートなりにコピーして、GitHubページのAccount->Settings->SSH and GPG keysのGPS keysにペーストします。このとき、GitHubに登録されているメールアドレスに、鍵の生成時に入力したメールアドレスが含まれている必要があります。

以上で、鍵の登録は終わりです。

# Commitに自動的にsignされるように設定

```shell
git config --global commit.gpgsign true
```

# signにつかうkeyの指定

```shell
git config --global user.signingkey 39D812AC # subkeyのID
```

# revoke(無効化)出来るようにしておく

秘密鍵のpassphraseを忘れてしまったり、秘密鍵を誰かに取られてしまうことって、よくありますよね。そんな時のために、鍵をrevokeする方法を事前に用意しておきます。

## revoke用の鍵を用意する

```shell
gpg --gen-revoke --output <file> C1356B8B  # pubkeyのID
```

これで、<file>にrevoke用の鍵が生成されます。実際にrevokeするときは、

```shell
gpg --import <file>
```

で出来ます。ただし、これはローカル環境の設定変更に過ぎないので、これを他の人に告知する必要があります。

そのためには、GitHubに登録した鍵を消去します。って、revoke key要らないね。

というのは冗談で、そんなことをしたら過去に署名したcommitなりtagなりが全てunverifiedとなってしまいます。それを防ぐために、revokeが使えます。

revokeをすると、pub keyにrevokeをした日時が書き込まれます(多分)。その新しいpub keyで、GitHubに登録してある古いpub keyを置き換えることで、revokeをした日時以前の署名は有効に、それ以降の署名は無効に出来ます。

また、気づいたかもしれませんが、この方法だと全てのsub keyがrevokeされます。それでは不便という場合には、特定のsubkeyのみrevokeすることもできます。

## 特定のsubkeyをrevokeする

これは事前に行うことはできません。おそらく、事前に行う必要がないからです。というのも、全てのsubkeyをrevokeしたい時というのは、pub keyの秘密鍵を盗まれた時か、pub keyのpassphraseを忘れた時で、後者の場合は事前にrevokeを作っておく必然性があります。ちなみに、sub keyのrevokeには、sub keyのpassphraseは必要ありません。

```shell
gpg --edit-key C1356B8B  # pubkeyのID
gpg> key n               # subkeyの表示順
gpg> revkey
gpg> save
```

# signする意味

### 多要素認証 

GitHubにpushするためには、ログインが必要です。じゃあ、それで認証になっているのではないかという話。これは、多要素認証のようなものではないかと思います。

ログインに必要な情報は、

- ユーザー名
- パスワード

です。これは、ユーザーに所属する情報です。

一方、signに必要な情報は、

- 秘密鍵

です。これは、システムに所属する情報です。

このように認証を行うことで、認証の確実性を向上させているのでしょう。

### 著作権

全てのファイルの冒頭に、

```python
# Copyright (C) 2019 <my name> and contributors
#
# This source code is licensed under the MIT License found in
# the LICENSE file in the root directory of this source tree.
```

などの表示をしていれば、全てのcontributerに同意を強制できる。というのも、署名の内容に著作権表示が含まれるので、署名がすなわち同意の証拠となる。OSS開発などで、権利の所在をはっきりさせるのに有効な手段だと思う。

# Troubleshooting

## Git: gpg: skipped "\<key id\>": No secret key エラー

このエラーが出る原因の一つに、gpgがどこにあるかをgitが知らないということがあります。僕は、Windows10でこの問題が起こっているのを見たことがあります。それに対処するために、署名に使うgpgがどこにあるのかをgitに教えるには、次のコマンドを実行します。

```shell
git config --global gpg.program "<path to gpg>"
```

# 余談
`gpg --list-keys`で出てくる`[SC]`や`[S]`といった記号の意味は、次の通りです。

|文字|意味|
|:-:|:--|
|E|encryption|
|S|signing|
|C|certification|
|A|authentication|

>
--list-options parameters
              This is a space or comma delimited string that gives options used when listing keys and signatures
              ...
              show-usage
                     Show  usage information for keys and subkeys in the standard key listing.  This is a list of letters indicating the allowed usage for
                     a key (E=encryption, S=signing, C=certification, A=authentication).  Defaults to yes.
(man gpg(1))

# 参考
- GitHubの登録
    - https://help.github.com/articles/generating-a-new-gpg-key/
- gpgの使い方
    - https://oguya.ch/posts/2016-04-01-gpg-subkeys/