🔰【Win/Mac】Gitコミットに署名（verifiedマーク）を付けよう！✍

Gitのコミットに署名をつけるための手順です✍🥒
※ 一番最後に動画を追加しました☘️

:::note
署名付きコミットは、ログ上にバッジが付きます。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142709/255c1504-41a9-7d08-dec1-1c123f0e91c0.png)

- Unverified - 何かが間違っていて認証に失敗したコミット
- Verified - 本人確認に成功したコミット（あるいはブラウザからGitHub上で行われたコミット）
- バッジなし - 署名がついていないコミット

署名付きコミットの検証について
[About commit signature verification - GitHub Docs](https://docs.github.com/ja/authentication/managing-commit-signature-verification/about-commit-signature-verification)（English）
:::

## 前提

- Windows10 
- 管理者アカウント
- Gitのユーザ設定が適切に設定されている（本記事の工程をすべて終えた後に設定してもOK）
    - `git config --global user.name`
    - `git config --global user.email`

:::note info
**Package managerを入れよう**
ソフトウェアインストールが楽になるのであらかじめ、Windowsなら[Chocolatey](https://chocolatey.org/install)、macOSなら[Homebrew](https://brew.sh/index_ja)を入れておきましょう！👀

- [Chocolateyのインストール方法](https://qiita.com/heppokofrontend/items/33f53db4e317712af0f8#chocolatey%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB) - `choco`コマンドが使えるようになる
- [Homebrewのインストール方法](https://qiita.com/heppokofrontend/items/e92d62b2a94b722d8eb4#homebrew%E3%82%92%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E3%81%99%E3%82%8B) - `brew`コマンドが使えるようになる

※ これらを利用しない場合でも、任意の方法で必要なソフトウェアをインストールできます
※ それぞれの記事の`choco`や`brew`以外の内容も見ていただけるとうれしいです☺
:::

:::note warn
ログやキャプチャはWindows 10で実施したものをサンプルとして掲載しています
:::

## 1. 環境を整えよう

まずはGPGがインストールされているかを確認しましょう。
シェルに、次のコマンドを入力してみます。

```shell
gpg --version
```

:::note 
**シェルとは**
- Windows：PowerShell
- macOS：ターミナル、iTerm2など
:::

:::note
**GPGのインストール方法は？**
```shell:Windows 10
choco install gpg4win -y
```
```shell:macOS
sudo brew install gpg
```
:::

GPGをインストールしたはずなのに「**gpgというコマンドを認識できない**」と言われた場合は、シェルを立ち上げ直してみましょう。

## 2. Gitの設定を確認しよう

シェルにそれぞれ入力し、設定しているユーザ名とメールアドレスを控えておきます。
何も値が出力されない場合は設定が誤っているので、Gitのユーザ設定を見直してください。

```shell
git config user.name
```

```shell
git config user.email
```

## 2. 秘密鍵を発行しよう

次のコマンドを入力します。

```shell
gpg --full-generate-key
```

### 質問に答えよう

いくつか質問されるので、回答していきましょう。

|設問|入力|備考|
|---|:--|:--|
|ご希望の鍵の種類を選択してください<br>あなたの選択は?|`1`|いくつか候補が出てきます。|
|RSA 鍵は 1024 から 4096 ビットの長さで可能です。<br>鍵長は?|`4096`|特に理由がなければ最大値に設定します。<br>参考：[公開鍵と秘密鍵のサイズに関する考慮事項 - IBM Documentation](https://www.ibm.com/docs/ja/zos/2.3.0?topic=certificates-size-considerations-public-private-keys)|
|鍵の有効期限を指定してください。<br>鍵の有効期間は?|任意|無期限でいい場合は`0`と入力します|
|これで正しいですか?|`y`|やり直す場合は`N`|
|本名|冒頭で控えた`user.name`の値||
|電子メール・アドレス|冒頭で控えた`user.email`の値||
|コメント||特に入力しなくてもOK|
|名前(N)、コメント(C)、電子メール(E)の変更、またはOK(O)か終了(Q)?|`O`|修正するものがなければ「O（おー）」を入力します|

```plain:例
gpg (GnuPG) 2.3.6; Copyright (C) 2021 g10 Code GmbH
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 (署名のみ)
   (9) ECC (署名と暗号化)
  (10) ECC (署名のみ)
  (14) カードに存在する鍵
あなたの選択は? 1
RSA 鍵は 1024 から 4096 ビットの長さで可能です。
鍵長は? (3072) 4096
要求された鍵長は4096ビット
鍵の有効期限を指定してください。
         0 = 鍵は無期限
      <n>  = 鍵は n 日間で期限切れ
      <n>w = 鍵は n 週間で期限切れ
      <n>m = 鍵は n か月間で期限切れ
      <n>y = 鍵は n 年間で期限切れ
鍵の有効期間は? (0)0
鍵は無期限です
これで正しいですか? (y/N) y

GnuPGはあなたの鍵を識別するためにユーザIDを構成する必要があります。

本名: XXXXXXXXXXXX
電子メール・アドレス: XXXXXXXXXXXX@example.com
コメント:
次のユーザIDを選択しました:
    "XXXXXXXXXXXX <XXXXXXXXXXXX@example.com>"

名前(N)、コメント(C)、電子メール(E)の変更、またはOK(O)か終了(Q)? O
```

ここまで進むと、パスワードを決めるように促されます。
安全なパスワードを考えて入力してください。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142709/48e94b32-c046-7286-38fa-e637984be115.png)

以上で鍵の生成は完了です。

#### うまくいったら・・・

次のような出力がされると思います。

```plain:例
gpg: 失効証明書を 'C:\\Users\\XXXXXXXXXXXX\\AppData\\Roaming\\gnupg\\openpgp-revocs.d\\XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.rev' に保管しました。
公開鍵と秘密鍵を作成し、署名しました。

pub   rsa4096 yyyy-mm-dd[SC]
      XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
uid                      XXXXXXXXXXXX <XXXXXXXXXXXX@gmail.com>
sub   rsa4096 yyyy-mm-dd [E]
```

:::note warn
**先に進まない！？**
> たくさんのランダム・バイトの生成が必要です。キーボードを打つ、マウスを動かす、ディスクにアクセスするなどの他の操作を素数生成の間に行うことで、乱数生成器に十分なエントロピーを供給する機会を与えることができます。

だいたい10秒かからない程度で鍵の生成は完了しますが、このメッセージで止まる場合は[エントロピープール](https://ja.wikipedia.org/wiki/%E3%83%8F%E3%83%BC%E3%83%89%E3%82%A6%E3%82%A7%E3%82%A2%E4%B9%B1%E6%95%B0%E7%94%9F%E6%88%90%E5%99%A8)が枯渇した状態になっています。
書かれている通り、キーボードを入力したりマウスを動かしたりして、鍵生成と関係ない別の作業をしてみてください。
:::

## 3. 秘密鍵のKey IDを取得しよう

まずはKey IDを取得します。
次のコマンドを実行してください。

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

すると以下のように、作った鍵の一覧が取得できます。

```plain:例
C:\Users\___user_name___\AppData\Roaming\gnupg\pubring.kbx
----------------------------------------------------------
sec   rsa4096/🥒🥒🥒 2022-06-21 [SC]
      XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
uid                 [  究極  ] XXXXXXXXXXXX <XXXXXXXXXXXX@gmail.com>
ssb   rsa4096/XXXXXXXXXXXXXXXX 2022-06-21 [E]
```

今回作った鍵の「🥒🥒🥒」の部分をコピーしてください。
この後で2回ほど使用します。

## 4. コミット時に使う鍵をGitくんに教えてあげよう

次のように、コピーしたKey IDを使ってGitの設定を変更します。
今回はグローバル設定を変更しますが、必要があればリポジトリごとの設定も行ってください。

```shell
git config --global user.signingkey 🥒🥒🥒
```

次のコマンドを入力すると設定内容が表示されます。

```shell
git config --global -e
```

`user`の項目に`signingkey`が増えていることが確認できたら成功です。
`:q!`と入力して終了しましょう（シェルを閉じてもOK）。

```diff_conf:.gitconfig
[user]
        email = XXXXXXXXXXXX@example.com
        name = XXXXXXXXXXXX 
+       signingkey = 🥒🥒🥒
```

## 5. 公開鍵を発行しよう

```shell
gpg --armor --export 🥒🥒🥒
```

無事に公開鍵が作れると、次のようなとても長い文字列が出力されます。

```plain:例
-----BEGIN PGP PUBLIC KEY BLOCK-----

めちゃくちゃ長い文字列
めちゃくちゃ長い文字列
めちゃくちゃ長い文字列

-----END PGP PUBLIC KEY BLOCK-----
```

「-----BEGIN PGP PUBLIC KEY BLOCK-----」から「-----END PGP PUBLIC KEY BLOCK-----」まですべてコピーしてください。

## 6. GitHubくんに公開鍵を渡そう

:::note 
**なぜGitHubくんに公開鍵を渡すの？**
今回、`gpg --full-generate-key`で作ったものは**秘密鍵**、`gpg --armor --export`で作ったものは**公開鍵**と呼ばれています。

公開鍵とは接続先に渡す南京錠で、「たくさんある情報の倉庫」の戸締りに使われます（暗号化用）。
秘密鍵とは、その南京錠を開けられる唯一の鍵です（復号用）。

「私のデータが改ざんされないように、書き換える権限はこの南京錠でしっかり戸締りしてね！」と、GitHubくんと約束するために公開鍵を渡さなければなりません。
:::

1. [GitHub](https://github.com/)にログインする
2. Settingsページから[SSH and GPG keys](https://github.com/settings/keys)ページを開く
3. **New GPG Key**ボタンをクリックする
4. テキストフィールド「**Title**」に任意の文字列を入力する（今お使いのPCの名前、たとえば「何代目Windows PC」とかでもOK）
5. テキストフィールド「**Key**」に**コピーした公開鍵**を貼り付ける
6. **Add GPG key**ボタンをクリックする

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142709/a4e79d40-424a-e2dc-3178-28442b0f274a.png)

## 7. コミット・プッシュしてみよう

任意のリポジトリにコミットを積んでみましょう。
その際、`-S`オプションをつけると証明書つきでコミットすることができます。

また、次の設定を適応すると`-S`オプションなしのデフォルトで署名付きコミットにすることができます。

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

:::note warn
**Windowsの方向け**
```
gpg: skipped "🥒🥒🥒": No secret key
```

というエラーが出る場合があるため、以下のコマンドも実行しておいてください。

```shell
git config --global gpg.program "C:\Program Files (x86)\GnuPG\bin\gpg.exe"
```
:::

任意のリポジトリにコミットを積んで`git push`できたら、GitHub上でコミットログを確認します。
無事、積んだコミットに「Verified」バッジがついてたら設定成功です！

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142709/b2b6ac7a-8b9b-1fc0-18d2-8d9d14b7bee4.png)

おつかれさまでした！🥳🥒

## おまけ：鍵の削除

誤って作ってしまった鍵や、不要になった鍵を削除する方法を紹介します。

### まずは秘密鍵を削除します

削除したい秘密鍵に紐づいたメールアドレスかKey ID（🥒🥒🥒）を添えて、`--delete-secret-keys`を実行します。

```shell
gpg --delete-secret-key メールアドレスまたはKey ID
```

実行後に出てくる設問とダイアログの内容をよく見て、問題なければ削除を実施します。

```plain:例
PS C:\Users\___user_name___> gpg --delete-secret-key XXXXXXXXXXXXXXX@example.com
gpg (GnuPG) 2.3.6; Copyright (C) 2021 g10 Code GmbH
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.


sec  rsa4096/XXXXXXXXXXXXXXXX 2022-06-21 XXXXXXXXXXXXXXX <XXXXXXXXXXXXXXX@example.com>

この鍵を鍵リングから削除しますか? (y/N) y
これは秘密鍵です! 本当に削除しますか? (y/N) y
```

### 続いて、公開鍵の削除です

公開鍵の削除には`--delete-key`を用います。

```shell
gpg --delete-key メールアドレスまたはKey ID
```

問題なければ削除を実施します。

```plain:例
PS C:\Users\___user_name___> gpg --delete-keys XXXXXXXXXXXXXXX@example.com
gpg (GnuPG) 2.3.6; Copyright (C) 2021 g10 Code GmbH
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.


pub  rsa4096/XXXXXXXXXXXXXXXX 2022-06-21 XXXXXXXXXXXXXXX <XXXXXXXXXXXXXXX@example.com>

この鍵を鍵リングから削除しますか? (y/N) y
```

## 参考文献

- [GitHub署名付きでコミットしてかっこつける](https://zenn.dev/appare45/articles/github-commit-sign)
- [コミットに署名する - GitHub Docs](https://docs.github.com/ja/authentication/managing-commit-signature-verification/signing-commits)
- [インポートしたGnuPGの公開鍵を削除するには － ＠IT](https://atmarkit.itmedia.co.jp/flinux/rensai/linuxtips/805delpubkey.html)
- [GPG キーを削除する方法](https://zenn.dev/noraworld/articles/delete-gpg-keys)
- [公開鍵と秘密鍵のサイズに関する考慮事項 - IBM Documentation](https://www.ibm.com/docs/ja/zos/2.3.0?topic=certificates-size-considerations-public-private-keys)

## ▶ 動画

今回の手順を実際にやってみました🥒


<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/silvQ-x79Qg" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>