🔑

GitHub へ GPG 署名つきでコミットする手順

2022/07/24に公開約13,300字2件のコメント

サマリー

GitHubGnuPG による署名つきのコミットを行うと Verified と表示されるようにします。

前提

  • Homebrew はインストール済み (macOS)
  • Git Bash もしくは何らかの Unix シェルを準備済み (Windows)
  • なんらかの GitHub レポジトリを作成済み

手順

1. git のインストール (macOS)

macOS に標準搭載されている git コマンドは少しバージョンが古いので、brew install コマンドで最新版をインストールします。

zsh
% brew install git
% which git

# Apple Silicon の場合
/opt/homebrew/bin/git

# Intel Mac の場合
/usr/local/bin/git

% git --version
git version 2.33.0

2. git の設定(その1)

まずは GitHub のアカウント名とメールアドレスを設定します。

zsh
% git config --global user.name "あなたの GitHub アカウント名"
% git config --global user.email "あなたのメールアドレス"

現在の設定を確認するには --list オプションを使います。

zsh
% git config --global --list
user.name=taro_foo
user.email=foo@example.com

また、ホームディレクトリへ .gitconfig というファイルが作られていることが確認できます。

zsh
% cat ~/.gitconfig
[user]
	name = taro_foo
	email = foo@example.com

3. gnupg (以下、gpg)のインストール (macOS)

環境にもよりますが、結構時間がかかります。

zsh
% brew install gnupg

% which gpg
/opt/homebrew/bin/gpg

% gpg --version
gpg (GnuPG) 2.3.1
libgcrypt 1.9.3
Copyright (C) 2021 Free Software Foundation, Inc.
License GNU GPL-3.0-or-later <https://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

4. pinentry-mac のインストール (macOS)

パスフレーズの入力ダイアログを提供する pinentry-mac というプログラムも必要となります。

pinentry-mac のインストール前に GnuPG の設定を保存するフォルダ ~/.gnupg を作成し、パーミッションを drwx------ に設定しておきます。

zsh
% mkdir ~/.gnupg
% chmod 700 ~/.gnupg

上の準備が出来たら、pinentry-mac をインストールします。

zsh
% brew install pinentry-mac

~ 中略 ~
==> Caveats
You can now set this as your pinentry program like

~/.gnupg/gpg-agent.conf
    pinentry-program /opt/homebrew/bin/pinentry-mac

Homebrew の指示に従って pinentry-program を設定します。

zsh
# `which pinenty-mac` で得られたパスを指定
% echo "pinentry-program $(which pinentry-mac)" >> ~/.gnupg/gpg-agent.conf

# 設定を反映させるため `gpg-agent` を再起動
% gpgconf --kill gpg-agent

5. gpg 鍵の作成

署名につかう gpg 鍵を作成します。
gpg --gen-key コマンドを実行してください。

zsh
% gpg --gen-key
gpg (GnuPG) 2.3.1; Copyright (C) 2021 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.

注意: 全機能の鍵生成には "gpg --full-generate-key" を使います。

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

本名: Taro Foo                      # <-- 名前を入力
電子メール・アドレス: foo@example.com  # <-- GitHub に登録したアドレスを入力
次のユーザIDを選択しました:
    "Taro Foo <foo@example.com>"

名前(N)、電子メール(E)の変更、またはOK(O)か終了(Q)? O  # <-- O を入力

pinentry のダイアログが表示されたら、パスワードを入力して OK をクリックしてください。

以下のようなメッセージが表示されたら、鍵作成の完了です。

zsh
たくさんのランダム・バイトの生成が必要です。キーボードを打つ、マウスを動か
す、ディスクにアクセスするなどの他の操作を素数生成の間に行うことで、乱数生
成器に十分なエントロピーを供給する機会を与えることができます。
gpg: 鍵D5335BA3024DD307を究極的に信用するよう記録しました
gpg: 失効証明書を '/Users/foo/.gnupg/openpgp-revocs.d/382DCB6AE30805248F3D05CFD5335BA3024DD307.rev' に保管しました。
公開鍵と秘密鍵を作成し、署名しました。

pub   ed25519 2021-08-19 [SC] [有効期限: 2023-08-19]
      382DCB6AE30805248F3D05CFD5335BA3024DD307
uid                      Taro Foo <foo@example.com>
sub   cv25519 2021-08-19 [E] [有効期限: 2023-08-19]

gpg -k コマンドで現在の公開鍵一覧を確認しましょう(-K オプションを使うと秘密鍵一覧)。

zsh
% gpg -k

gpg: 信用データベースの検査
gpg: marginals needed: 3  completes needed: 1  trust model: pgp
gpg: 深さ: 0  有効性:   2  署名:   0  信用: 0-, 0q, 0n, 0m, 0f, 2u
gpg: 次回の信用データベース検査は、2022-11-28です
/Users/foo/.gnupg/pubring.kbx
-------------------------------
pub   ed25519 2021-08-18 [SC] [有効期限: 2023-08-18]
      73E939B96DA34BCB70CBD4923D5480AA3DF9D84F
uid           [  究極  ] Taro Foo <foo@example.com>
sub   cv25519 2021-08-18 [E] [有効期限: 2023-08-18]

6. gpg 公開鍵のエクスポート

この鍵を GitHub に登録するため、ファイルへ公開鍵をエクスポートします。

zsh
% gpg -a --export "あなたのメールアドレス" > pubkey.gpg

-a オプションを用いることで平文(プレーンテキスト)で出力されます。

zsh
% cat pubkey.gpg
-----BEGIN PGP PUBLIC KEY BLOCK-----

mDMEYR2cyRYJKwYBBAHaRw8BAQdAfczM5JrK6r8U+x+rQoiEbRYIeEoXbtGGU42h
N1OMaBy0HFRhcm8gWmVubiA8emVubkBleGFtcGxlLmNvbT6ImgQTFgoAQhYhBHPp
Oblto0vLcMvUkj1UgKo9+dhPBQJhHZzJAhsDBQkDwmcABQsJCAcCAyICAQYVCgkI
CwIEFgIDAQIeBwIXgAAKCRA9VICqPfnYT5jCAQCI5zeN+wycTrNmf02+Cr6hzEDk
kDbgiRGr3+NOqdADUQD9H933zY3qNcx2qvgLENaA0ieA0cHqv+8pqnzutJH0DQq4
OARhHZzJEgorBgEEAZdVAQUBAQdANNhjv3+GT+/wSaQl8icZQZvaB/gelzRSQydj
ueteJC8DAQgHiH4EGBYKACYWIQRz6Tm5baNLy3DL1JI9VICqPfnYTwUCYR2cyQIb
DAUJA8JnAAAKCRA9VICqPfnYTw9VAQCRJT53OHlsg3wvl9gTLbBjQ8zogLF+Kyml
DUS96PxdPgD/bvdup4CpUqwMovTygdrYOgYIa9G+4eCaaVptPnldcwU=
=Qold
-----END PGP PUBLIC KEY BLOCK----

7. gpg 秘密鍵のエクスポート

秘密鍵をファイルへエクスポートし、このファイルは大切に保管してください。

zsh
% gpg -a --export-secret-key "あなたのメールアドレス" > seckey.gpg

8. 既存の gpg 鍵をインポートする場合

すでに gpg 鍵を作成済みの場合は、その鍵の秘密鍵をインポートします。

zsh
% gpg --import seckey.gpg

pinentry のダイアログが表示されたらパスフレーズを入力して OK をクリックします。

以下のように表示されればインポートは成功です。

zsh
gpg: 鍵D594B27E9EE46CB4: 公開鍵"Taro Foo <foo@example.com>"をインポートしました
gpg: 鍵D594B27E9EE46CB4: 秘密鍵をインポートしました
gpg:           処理数の合計: 1
gpg:             インポート: 1
gpg:       秘密鍵の読み込み: 1
gpg:     秘密鍵のインポート: 1

gpg -k コマンドで確認しましょう。

zsh
% gpg -k
gpg: 信用データベースの検査
gpg: marginals needed: 3  completes needed: 1  trust model: pgp
gpg: 深さ: 0  有効性:   1  署名:   0  信用: 0-, 0q, 0n, 0m, 0f, 1u
gpg: 次回の信用データベース検査は、2022-11-28です
/Users/foo/.gnupg/pubring.kbx
-------------------------------
pub   ed25519 2021-08-19 [SC] [有効期限: 2023-08-19]
      0536B7DDDAD6517D838D9761D594B27E9EE46CB4
uid           [  不明  ] Taro Foo <foo@example.com>
sub   cv25519 2021-08-19 [E] [有効期限: 2023-08-19]

鍵の信頼度が [ 不明 ] となってしまっているので、これを gpg --edit-key コマンドで修正します。

zsh
% gpg --edit-key "あなたのメールアドレス"
gpg (GnuPG) 2.3.1; Copyright (C) 2021 Free Software Foundation, Inc.

# ~ 省略 ~

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

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

あなたの決定は?   # <-- 1~5 の数字を入力して Enter

通常は自分が作成した鍵であることは明白でしょうから、大抵の場合は 5 を入力することになるでしょう。

zsh
あなたの決定は? 5
本当にこの鍵を究極的に信用しますか? (y/N) y  # <-- `y` を入力(大文字の選択肢のほうがデフォルト)

# ~ 省略 ~

プログラムを再起動するまで、表示された鍵の有効性は正しくないかもしれない、
ということを念頭においてください。

gpg> quit  # <-- `quit` と入力して編集画面を終了

再度、gpg -k コマンドで確認しましょう。

zsh
% gpg -k

gpg: 信用データベースの検査
gpg: marginals needed: 3  completes needed: 1  trust model: pgp
gpg: 深さ: 0  有効性:   2  署名:   0  信用: 0-, 0q, 0n, 0m, 0f, 2u
gpg: 次回の信用データベース検査は、2022-11-28です
/Users/foo/.gnupg/pubring.kbx
-------------------------------
pub   ed25519 2021-08-19 [SC] [有効期限: 2023-08-19]
      0536B7DDDAD6517D838D9761D594B27E9EE46CB4
uid           [  究極  ] Taro Foo <foo@example.com>
sub   cv25519 2021-08-19 [E] [有効期限: 2023-08-19]

9. GitHub へ gpg 公開鍵を登録する

GitHub の Settings>SSH and GPG keysページを開き、New GPG key ボタンをクリックします。

エクスポートされた公開鍵の内容をここへコピー&ペーストし、Add GPG key ボタンをクリックします。

zsh
# macOS
% cat pubkey.gpg | pbcopy

# Windows (Git Bash)
$ cat pubkey.gpg > /dev/clipboard

# 公開鍵の内容がクリップボードへ送られたので、
# これをブラウザの画面へ Cmd+V or Ctrl+V でペーストする


適当なタイトルをつけて "Key" へペースト

10. SSH 鍵の作成

つづいて GitHub へ登録する SSH 鍵を作成します。

https://docs.github.com/en/github/authenticating-to-github/connecting-to-github-with-ssh/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent

ssh-keygen コマンドを実行してください。

zsh
% ssh-keygen -t rsa -b 4096 -C "あなたのメールアドレス"

Generating public/private rsa key pair.
Enter file in which to save the key (/Users/foo/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /Users/foo/.ssh/id_rsa.
Your public key has been saved in /Users/foo/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:M6jeZYosBNpMU93jEpr2IJUJY91wlYpBFvhoxucsV6Q foo@example.com
The key's randomart image is:
+--[rsa 256]--+
|  +==B.o..       |
| ..oB.= +        |
| . = B + .       |
|. O E +..        |
|.B B +..S        |
|. = +..  o       |
| . o.   o        |
|  .o o +         |
|   .+ o          |
+----[SHA256]-----+

Enter 連打でも SSH 鍵自体は作成できますが、適宜パスワードや出力ファイル名などを設定してください。

11. GitHub へ SSH 公開鍵を登録する

ふたたび Settings>SSH and GPG keysページを開き、New SSH key ボタンをクリックします。

Title へ適当なタイトルを付け、 Key~/.ssh/id_rsa.pub の内容をコピー&ペーストします。

zsh
# macOS
% cat ~/.ssh/id_rsa.pub | pbcopy

# Windows (Git Bash)
$ cat ~/.ssh/id_rsa.pub > /dev/clipboard

12. SSH 接続の設定

ssh github のコマンド実行のみで GitHub へ SSH 接続できるように ~/.ssh/config ファイルを作成します。

.ssh/config
Host github
  HostName github.com
  User git
  IdentityFile ~/.ssh/id_rsa

13. GitHub へ SSH 接続してみる

では、さっそく SSH 接続してみましょう。

zsh
% ssh github

~ 中略 ~
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
                                                         # <-- yes と入力

PTY allocation request failed on channel 0
Hi foo! You've successfully authenticated, but GitHub does not provide shell access.
Connection to github.com closed.

「認証できたけど、GitHub ではシェルアクセスを提供していないので切断するよ」という旨のメッセージが表示されれば成功です。

14. git の設定(その2)

コミット時に gpg による署名を必要とするように設定を追加します。

zsh
# 公開鍵一覧の確認
% gpg -k
/Users/foo/.gnupg/pubring.kbx
-------------------------------
pub   ed25519 2021-08-19 [SC] [有効期限: 2023-08-19]
      382DCB6AE30805248F3D05CFD5335BA3024DD307
uid           [  究極  ] Taro Foo <foo@example.com>
sub   cv25519 2021-08-19 [E] [有効期限: 2023-08-19]

# gpg コマンドのパスを登録
% git config --global gpg.program `which gpg`

# 上の gpg -k コマンドで表示された鍵の ID を指定
% git config --global user.signingkey "382DCB6AE30805248F3D05CFD5335BA3024DD307"

# コミット時に gpg による署名をおこなう
% git config --global commit.gpgsign true

# 設定の確認
% git config --global --list

user.name=taro_foo
user.email=foo@example.com
user.signingkey=382DCB6AE30805248F3D05CFD5335BA3024DD307
gpg.program=/opt/homebrew/bin/gpg
commit.gpgsign=true

15. 署名つきでコミットしてみる

適当なディレクトリを作成し、git レポジトリとして初期化します。

zsh
% mkdir gpg-test
% cd gpg-test
% git init

空のファイルを作成し、これをコミットしてみましょう。

zsh
% touch empty.txt
% git add -A
% git commit -m "first commit"

macOS

pinenty のダイアログが表示されれば、これで gpg のための設定は完了です。
Save in Keychain のチェックはお好みでどうぞ。

Windows

CredentialHelperSelector が表示されたら、そのまま Select をクリックします。
Always use this from now on のチェックはお好みでどうぞ。

pinenty のダイアログが表示されれば、これで gpg のための設定は完了です。

16. GitHub レポジトリの設定

すでに存在する GitHub レポジトリで、そのレポジトリの特定ブランチへの PUSH 時には gpg 署名が必須となるように設定します。

対象としたい GitHub レポジトリのページから、Settings>Branches へとすすみ、Add rule ボタンをクリックします。

Branch name pattern へ対象とするブランチ名を入力し、

Require signed commits をチェックして Create ボタンをクリックします。

最後に Save changes ボタンをクリックして完了です。

17. GitHub へプッシュしてみる

では、このブランチへプッシュしてみましょう。

zsh
% git push

Warning: Permanently added the RSA host key for IP address '52.192.168.89' to the list of known hosts.
Enumerating objects: 7, done.
Counting objects: 100% (7/7), done.
Delta compression using up to 8 threads
Compressing objects: 100% (4/4), done.
Writing objects: 100% (4/4), 1.21 KiB | 1.21 MiB/s, done.
Total 4 (delta 3), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (3/3), completed with 3 local objects.

~ 以下略 ~

このコミットから Verified となりました。

Discussion

設定できました。ありがとうございます。

ただ書かれた通りの手順に従うだけだと~/.gnupgが無くて失敗するところがありました。そこでmkdir ~/.gnupgだけして進むと次のような警告が出て、コミット時にpinentyが起動しないようでした。

gpg: *警告*: homedir '/Users/${USER}/.gnupg'の安全でない許可

次の2行を追加すると良いように思います。

+ % mkdir ~/.gnupg
+ % chmod 700 ~/.gnupg
# `which pinenty-mac` で得られたパスを指定
% echo "pinentry-program $(which pinentry-mac)" >> ~/.gnupg/gpg-agent.conf

@nabeyang さん
ご指摘ありがとうございます。
GPG鍵を作成する前に pinentry-program の設定をしていることが失敗の原因でした。
加筆修正いたしました。ありがとうございました。

ログインするとコメントできます