Smile Engineering Blog

ジェイエスピーからTipsや技術特集、プロジェクト物語を発信します

GitHub の Verified マーク

はじめに

GitHub にて、Web ブラウザ上でプルリクエストをマージした際に Verified マークが付いていることに気づきました。自分のコミットも Verified されたい!という事で、備忘のため手順を残しておきます。

Verified マーク

f:id:jspnet:20200812124618p:plain

Git にはコミットやタグに署名を付与し、これを検証する仕組みが備わっています。GitHub の場合、検証をパスしたコミットやタグに Verified がマークされます。GitHub Docs によると、

GitHub は、GitHub Web インターフェイスを使用して自動的にコミットに署名します。

とあります。「Web ブラウザ上でプルリクエストをマージした際に」 Verified マークが付与されたのはそのためですね。

今回解説するのはコミットやタグをローカルで署名して、GitHub で検証させる(Verified マークを付与する)方法です。

確認した環境

  • Ubuntu 20.04.1 LTS
  • Git 2.25.1
  • gpg 2.2.19
  • zsh 5.8

GPG

GPG(GNU Privacy Guard)とは、OpenPGP という規格に従って GNU が作成した暗号化ソフトウェアです。コミットやタグの署名・検証に使用します。

準備

事前に、

  • 署名の検証を行う GitHub には GPG キーを登録
  • コミットやタグに署名を行う Git には GPG 署名キーを登録

しておく必要があります。手順は次のとおりです。

  1. 新しい GPG キーを作成する
  2. GitHub アカウントへの GPG キーを追加する
  3. Git へ GPG 署名キーを設定する

1. 新しい GPG キーを作成する

新しい GPG キーを作成するには以下のコマンドを使用します。いくつかの問い合わせの後、GPG キー、および GPG 署名キーが作られます。

gpg --full-gen-key

以下はコマンド投入後、GitHub docs の手順に従って入力した例です。途中、パスフレーズの入力を促されるので安全なパスフレーズを入力します。また、メールアドレスには GitHub アカウント用の検証済みメールアドレスを入力する必要があります。

bob@11-1fc0-1-2 ~ % gpg --full-gen-key
gpg (GnuPG) 2.2.19; Copyright (C) 2019 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)
  (14) Existing key from card
Your selection? 1                                       # 鍵の種類を選択(RSA and RSA)
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (3072) 4096                   # 鍵の bit 数を指定
Requested keysize is 4096 bits
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) 0                                 # 鍵の有効期限を指定(無期限)
Key does not expire at all
Is this correct? (y/N) y                                # yes!

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

Real name: Bob Marley                                   # 名前を入力
Email address: bob@example.com                          # メールアドレスを入力
Comment:                                                # コメントを入力(未入力)
You selected this USER-ID:
    "Bob Marley <bob@example.com>"

Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? O   # Okay!
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
gpg: key C611EFD63CD09CA7 marked as ultimately trusted
gpg: directory '/home/bob/.gnupg/openpgp-revocs.d' created
gpg: revocation certificate stored as '/home/bob/.gnupg/openpgp-revocs.d/314EC2737F246F907368BA38C611EFD63CD09CA7.rev'
public and secret key created and signed.

pub   rsa4096 2020-08-11 [SC]
      314EC2737F246F907368BA38C611EFD63CD09CA7
uid                      Bob Marley <bob@example.com>
sub   rsa4096 2020-08-11 [E]

GPG キーが作成されました。以降、ここで作成したキーをもとに説明を進めます。

2. GitHub アカウントへ GPG キーを追加する

作成した GPG キーのリストを表示するには以下のコマンドを使用します。

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

作成した GPG キーのリストを表示させてみます。

bob@11-1fc0-1-2 ~ % gpg --list-secret-keys --keyid-format LONG
gpg: checking the trustdb
gpg: marginals needed: 3  completes needed: 1  trust model: pgp
gpg: depth: 0  valid:   1  signed:   0  trust: 0-, 0q, 0n, 0m, 0f, 1u
/home/bob/.gnupg/pubring.kbx
-----------------------------
sec   rsa4096/C611EFD63CD09CA7 2020-08-11 [SC]
      314EC2737F246F907368BA38C611EFD63CD09CA7
uid                 [ultimate] Bob Marley <bob@example.com>
ssb   rsa4096/D3375CB42A265387 2020-08-11 [E]

以下のコマンドで GPG キーを表示することができます。

gpg --armor --export <GPG キー ID>

上の例だと GPG キー ID は C611EFD63CD09CA7 です。

bob@11-1fc0-1-2 ~ % gpg --armor --export C611EFD63CD09CA7
-----BEGIN PGP PUBLIC KEY BLOCK-----

mQINBF8yctkBEACcX04i4H6+WW7ZX1MQF0+RLfHmNVO7zqcFd+wKUgCnHdN5qYsD
kHSqM3TWGcIUVl7AxjxTFPitJJGe5O58tIQies62pWbqAifXcAaxYee9FL2vTDWz
:
-----END PGP PUBLIC KEY BLOCK-----

-----BEGIN PGP PUBLIC KEY BLOCK----- で始まり、-----END PGP PUBLIC KEY BLOCK----- で終わる部分が GPG キーです。これをコピーして GitHub アカウントに登録します。登録手順は次のとおりです。

  1. GitHub の任意のページの右上のプロフィール画像をクリックし Settings を選択
  2. ユーザ設定サイドバーで SSH and GPG Keys を選択し New GPG Key をクリック
  3. Key フィールドにコピーした GPG キーを貼り付ける
  4. Add GPG Key をクリックして登録完了(GitHub アカウントのパスワードを求められる)

これで GitHub への設定(追加)は完了しました。

3. Git へ GPG 署名キーを設定する

Git への GPG 署名キーの設定は以下のコマンドで行います。GPG キー ID を介して設定されます。

git config --global user.signingkey <GPG キー ID>

上の例だと GPG キー ID は C611EFD63CD09CA7 なので、

git config --global user.signingkey C611EFD63CD09CA7

これで Git への設定は完了しました。

注意!

bash の場合、環境変数 GPG_TTY の設定が必要かもしれません。その場合、以下を実行してください。

$ test -r ~/.bash_profile && echo 'export GPG_TTY=$(tty)' >> ~/.bash_profile
$ echo 'export GPG_TTY=$(tty)' >> ~/.profile

署名

では実際に署名してみます。署名には、

  • コミットの署名
  • タグの署名

の 2 種類があります。

コミットに署名する

コミットに署名するには -S オプションを使用します。

git commit -S -m <your commit message>

コミットしてみます。署名(コミット)の際には GPG キー作成の際に使用したパスフレーズの入力を求められます。

bob@11-1fc0-1-2 ~ % git commit -S -m 'signed commit'
[master 29591c6] signed commit
 1 file changed, 1 insertion(+), 1 deletion(-)

署名の確認・検証を行うには git log コマンドの --show-signature オプションを使用します。

bob@11-1fc0-1-2 ~ % git log --show-signature -1
commit 29591c6dcb8e791695b41a3eefeebed542715055 (HEAD -> master)
gpg: Signature made 2020年08月11日 09時39分56秒 JST
gpg:                using RSA key 314EC2737F246F907368BA38C611EFD63CD09CA7
gpg: Good signature from "Bob Marley <bob@example.com>" [ultimate]
Author: Bob Marley <bob@example.com>
Date:   Wed Aug 11 09:39:56 2020 +0900

    signed commit

署名の状態を表示したいだけであれば format で %G? で表示できます。

bob@11-1fc0-1-2 ~ % git log --pretty="format:%h %G? %aN  %s"
29591c6 G Bob Marley  signed commit
1beae74 N Bob Marley  unsigned commit
c139a11 E Bob Marley  Initial commit

%G? の意味:

%G? mean
G good (valid) signature
B bad signature
U good signature with unknown validity
X good signature that has expired
Y good signature made by an expired key
R good signature made by a revoked key
E if the signature cannot be checked (e.g. missing key)
N no signature

では GitHub にプッシュしてみましょう。プッシュ後、Web ブラウザでコミット一覧を表示します。

f:id:jspnet:20200812124712p:plain

コミットに対して Verified マークが付与されています!GPG キー ID も同じになってます。

タグに署名する

タグに署名するには -s オプションを使用します。

git tag -s <mytag>

署名してみます。署名(タグ付け)の際には GPG キー作成の際に使用したパスフレーズの入力を求められます。

git tag -s v1.1.0

署名の検証を行うには -v オプションを使用します。

git tag -v <mytag>

検証してみます。

bob@11-1fc0-1-2 ~ % git tag -v v1.1.0
object 29591c6dcb8e791695b41a3eefeebed542715055
type commit
tag v1.1.0
tagger Bob Marley <bob@example.com> 1597109458 +0900

v1.1.0
gpg: Signature made 2020年08月11日 10時30分58秒 JST
gpg:                using RSA key 314EC2737F246F907368BA38C611EFD63CD09CA7
gpg: Good signature from "Bob Marley <bob@example.com>" [ultimate]

では GitHub にプッシュしてみましょう。プッシュ後、Web ブラウザでタグ一覧を表示してみます。

f:id:jspnet:20200812124733p:plain

タグに対して Verified マークが付与されています!こちらも GPG キー ID が同じになってますね。

おわりに

とりあえず Verified マークを付与することはできましたが、署名の検証によってマージやプルの振る舞いを変える(有効な署名が無いコミットは拒否する)こともできるみたいです。それはまた別の機会に。

参考