なりすまし防止！Githubへの署名付きコミット

　こんにちは！バイオインフォマティクス系オタク修士学生のroadricefieldです！今日はGithub上で各コミットを本当に自分が行ったということを証明するお話です。  

# 何が起きたのか  

　僕は気づいてしまったんです... ホームディレクトリの`.gitconfig`のメールアドレスを誰かがGithubアカウントに登録しているメールアドレスに書き換えると以降の自分のすべてのコミットをその誰かのアカウントが行ったとGithub上では表示されることに...  

```:.gitconfig
[user]
        email = <Email address>
        name = <User name>
```  

　ほんとなんです！！気になる君はお友達とやってみよう！お友達がいない君は<ruby>新しいGithubアカウント<rp>（</rp><rt>おともだち</rt><rp>）</rp></ruby>を作ってやってみよう！  

　これを利用すれば他人を陥れることが可能なのではないかと心配になりました。

# Github文庫『それでも僕はコミットしてない』  

　完全自立型介護ロボット「MIRAI」の制御プログラムの開発は終盤に差し掛かっていた。  

「おれ、この案件が終わったら彼女にプロポーズしようと思うんだ」  

　そう隣で誰も聞いてもいないのに語り始めたのは僕の同期、E君だ。彼はとても優秀で次の人事での昇進は確実だと言われている。おまけにとてもかわいくてやさしい彼女がいて、E君の人生は順風満帆だった。  
  
◇◇◇
  
　「MIRAI」は無事発売され、全国の介護施設で運用がスタートした。売れ行きはとても良く、僕たちの会社はまたたく間に成長し、数年後には業界トップになった。「MIRAI」への貢献が大きいE君は若くして部長に就任した。社員の給料もどんどん上がり、独身貴族の僕もウハウハだった。  

◇◇◇  

　僕たちの幸せな日々はそう長くは続かなかった。「MIRAI」による事故が全国で多発し始めたのだ。突如天国から地獄に叩き落された会社は必死に原因を究明した。その結果、「MIRAI」の制御プログラムに外部からの通信により誤作動を起こす仕組みが発見され、すぐさまGithubのコミットログが調べられた。  
  
　その部分を書いてコミットしていたのはE君だった。E君は全く知らない、誰かに仕組まれたと主張したが残念ながら誰もE君を信じようとはしなかった。
  
「それでも僕はコミットしてない」  

　E君は最後にそう言い残して会社をやめていった。  

◇◇◇ 

　E君は事あるごとに僕を見下すような発言をする人だった。しかも僕の彼女を奪って挙句の果てには僕の隣でプロポーズを宣言しやがった。僕はあの日、E君に復讐しようと誓った。  

```
$ cd
$ vim .gitconfig
```  
　僕はターミナルにそう打ち込んで`.gitconfig`を編集する。  

```:.gitconfig
[user]
        email = E-kun@qiitasoft.com
        name = E-kun
```  

　`:wq`で保存してそのまま事前に用意していたあのソースコードをプッシュする。  

``` 
$ git push origin master
```  

　プッシュするときのユーザー名とパスワードは自分のを入力すればいい。ブラウザでコミットログを調べるとたしかにE君がコミットしたことになっていた。こまめにコミットするE君は一個だけ身に覚えがない自分のコミットがあることに気づかない。これで僕の完全犯罪が成立した。さて、いつ破滅させてやろうか...  


# E君のようにならないためには  

　実際にこんなことが起きたらたまったものではないので自分がコミットをしたんだということを証明できるようにしたいところです。Githubにはコミットに署名をしてそれを検証してくれる機能があります。この記事ではWSL (Windows Subsystems for Linux)でのその一連の操作を紹介します。  

## GPGキーの作成  

　まず署名に使用するGPGキーという鍵を作成します。  

```
$ gpg --full-generate-key
```  

　これを入力すると以下のようなメッセージが表示されます。  

```
gpg (GnuPG) 2.2.4; Copyright (C) 2017 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.

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)
Your selection?
```  

　defaultで良いようなのでなにもせずに`Enter`を押します。  

```
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (3072)
```  

　Githubによるとここは4096 bitにしてほしいらしいので`4096`と入力して`Enter`。

```
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`。  

```
Key does not expire at all
Is this correct? (y/N)
```  

　`y`と入力して`Enter`。

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

Real name: E-kun
Email address: E-kun@qiitasoft.com
Comment:
```  

　情報を入力してください。このとき、`Email address`には`.gitconfig`に書いているものを入力してください。`Comment`には何か入力してもいいですし、何も書かなくてもいいです。鍵は複数作れるようなのでもし失敗したらもういちど作り直してください。入力したら`Enter`。

```
You selected this USER-ID:
    "E-kun (dammy) <E-kun@qiitasoft.com>"

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

修正したいところがなければ`O`と入力して`Enter`。  

　次に、パスフレーズの登録を求められます。少なくとも一文字は数字を含める必要があるようです。  

　パスフレーズの入力が終わったら、

```
$ gpg --list-secret-keys --keyid-format LONG
```  

すると

```
/Users/hubot/.gnupg/secring.gpg
------------------------------------
sec   4096R/3AA5C34371567BD2 2016-03-10 [expires: 2017-03-10]
uid                          Hubot 
ssb   4096R/42B317FD4BA89E7A 2016-03-10
```  

このような出力を得ます。この例は[Github公式](https://help.github.com/ja/github/authenticating-to-github/generating-a-new-gpg-key)のものをお借りしました。`sec`から始まる行の`/`の後、この例で言うところの`3AA5C34371567BD2`がキーIDと呼ばれるものだそうです。  

　GPGキーを出力します。

```
$ gpg --armor --export 3AA5C34371567BD2
```  

`3AA5C34371567BD2`は自分のキーIDに置き換えてください。すると「この画像の中であなたが最初に見つけた5つの言葉があなたの人生を表すキーワード」みたいなのがでてくるので`-----BEGIN PGP PUBLIC KEY BLOCK-----`で始まり、`-----END PGP PUBLIC KEY BLOCK-----`で終わる部分をコピーしてください。  

## 作ったGPGキーをGithubアカウントに登録する

　Githubに自分のアカウントでログインして右上の自分アバターをクリック -> `Settings` -> 左のメニューの中の`SSH and GPG keys`をクリック -> `New GPG key`をクリック -> 出てきたwindowに先程のGPGキーをペースト -> `Add GPG key`をクリック  

　これでアカウントへのGPGキーの登録はおしまいです。  

## Gitに署名用のGPGキーを登録する  

　ターミナルに戻って

```
$ git config --global user.signingkey 3AA5C34371567BD2
```

を実行します。`3AA5C34371567BD2`は自分のキーIDに置き換えてください。もし忘れた場合はもう一度

```
$ gpg --list-secret-keys --keyid-format LONG
``` 

で表示してください。  

## WSLだけ？で必要だった謎操作  

　私のWSL環境では以下をホームディレクトリの`.bash_profile`か`.bashrc`に書き加える必要がありました。  

```
export GPG_TTY=$(tty)
```  
このあと先程登録したパスフレーズの入力を求められるのですがこれをやっておかないとその入力画面が立ち上がらず、失敗するようです。（謎）`$ source .bash_profile`かWSLを再起動するのを忘れないでください。  

## 署名付きでコミットする  

　署名付きでコミットするにはコミットの際に`-S`オプションを付け足すだけです。  

```
$ git commit -m "Verify test" -S
```  

先程のパスフレーズの入力を求められます。

```
$ git push origin <branch名>
```  

　プッシュしたらブラウザでコミットログを確認してください。  

![verified.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/477619/e5852de1-9710-43d5-98e4-700fd735418f.png)

　このように`Verified`と表示されていればそのコミットは署名付きになっています。確かにあなたがコミットしており、なりすましではないことが保証されているという形になります。  

# 引用 

　この記事は以下のGithub公式での説明を再構成して書いたものです。

- [コミット署名の検証を管理する](https://help.github.com/ja/github/authenticating-to-github/managing-commit-signature-verification)  
- [新しい GPG キーを生成する](https://help.github.com/ja/github/authenticating-to-github/generating-a-new-gpg-key)  
- [GitHub アカウントへの新しい GPG キーの追加](https://help.github.com/ja/github/authenticating-to-github/adding-a-new-gpg-key-to-your-github-account)
- [Git へ署名キーを伝える](https://help.github.com/ja/github/authenticating-to-github/telling-git-about-your-signing-key)
- [コミットに署名する](https://help.github.com/ja/github/authenticating-to-github/signing-commits)  

　さらにWSL特有（？）の問題の解決法は以下で見つけました。  

- [WSL Ubuntu: git gpg signing Inappropriate ioctl for device](https://github.com/microsoft/WSL/issues/4029)