13
13

More than 3 years have passed since last update.

GitHub / GitLab用にコミット署名を行うための準備メモ

Last updated at Posted at 2019-12-26

この記事について

 普段GitHubではプライベートなリポジトリーしか使ってこなかったのですが、Qiitaに記事を投稿したりする際はパブリックなリポジトリーも必要だと思い、いろいろ準備をしました。そのうちの一つについてまとめてみました。
 世に公開されているプロジェクト(リポジトリー)の中にはプルリクを出す際に「コミットに署名付けること必須」みたいなケースがあったりします。
 私の場合、署名が必須なリポジトリーにプッシュすることは当面ありませんが、コミットに署名を付けられるように準備しました。

表記ゆれについて

 この記事では「コミット署名」「コミットに署名を付ける」「コミットに電子署名を付ける」など表記に揺れがありますが、いずれも同じこととして読み進めてください。略して記載する場合は「コミット署名」と記載します。

「コミットに署名を付ける」とは

 GitはGPGやS/MIMEを用いてコミットに対して電子署名を付けることができます。電子署名に使用した秘密鍵の対となる公開鍵を所有している第三者は「コミットした人は、秘密鍵を持っている人だ」と検証することができます。ただし、なりすまし判定についてはやや事情が複雑です。

 S/MIMEの詳細説明は割愛しますが、VeriSignなどのパブリック認証局は本人確認(もしくは実在確認)をしたうえで公開鍵の正しさを証明する電子証明書を発行するので、基本的になりすますことはできません(正確な情報を知りたい方はネットで調べてください)。

 一方GPGの場合、基本的に電子署名に必要な鍵の生成は利用者が行います。そのため「これは @cocoabreak の公開鍵だよ」となりすまして偽の公開鍵を配布することができます。通常この手のなりすましを防ぐために「信頼の輪」と呼ばれる仕組みを用いますが、GitHubやGitLabが公開鍵をどのようにして信頼しているかは後程述べます。

※信頼の輪:受け取った公開鍵が本人のもであることが確認出来たら、その公開鍵に対して電子署名を付けてあげます。こんな感じでお互いに公開鍵に電子署名を付けて信頼を広げていくのが「信頼の輪」です。

 長々と書いてしまいましたが、次からは設定編です。

GPGの準備

 今回はWindowsを使う場合の手順です。インストール関連以外はmacOSやLinuxでもほとんど同じです。

GPGをインストールする

 鍵を作成するにはGPGが必要です。今回はアルゴリズムにはRSAではなくECC(楕円曲線暗号)を用いることにしました。
 実はGit(Git for Windows)をインストールするとGPGも使えるようになります。ネットに転がってる古い記事だとGit for WindowsのGPGは1.4系(classic)でECCが使えない、といった記述もあるのですが、Git for Windows v2.24.1に関して言えば、GPGのv2.2.18がバンドルされています。

 したがって、わざわざECCのためにGPGをインストールする必要はありません。Gpg4winを使いたい場合や、どうしても最新版をインストールしたいといった場合にGPGをインストールしましょう。

 ちなみに、私は古い記事を鵜呑みにしてインストールしたわけではなく、鍵関連のファイルをscoop管理下に置きたかったからです。自分で確認することもせず古い記事を鵜呑みにしたわけではありません(大切なので二回書きます)。

 インストールモジュールは The GNU Privacy Guard からダウンロードすることができますが、自分はscoopを使いました。

scoop install gpg

 鍵は次のフォルダーに格納されます。

  • Git for Windows同梱のGPGの場合
    • %HOMEPATH%\.gnupg
  • scoopでインストールしたGPGの場合
    • %HOMEPATH%\scoop\apps\gpg\current\home

 続いて鍵を作成します。

鍵を作成する

 単純に鍵を作成してもよいのですが、今回は「信頼の輪」を考慮して、マスター鍵/サブ鍵構成にすることにしました。このようにしておくと「信頼の輪」を維持したままサブ鍵を再発行することができます。

マスター鍵を作成する

 鍵作成のコマンドはgpg --full-gen-keyですが、今回はECCを使用したいので--expertオプションを追加します。
 マスター鍵は認証(Certify)のみできる鍵にしたいため、鍵の種類は11を選択します。

PS C:\Users\cocoabreak> gpg --full-gen-key --expert 
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.

gpg: keybox'C:/Users/cocoabreak/scoop/apps/gpg/current/home/pubring.kbx'が作成されました
ご希望の鍵の種類を選択してください:
   (1) RSA  RSA (デフォルト)
   (2) DSA  Elgamal
   (3) DSA (署名のみ)
   (4) RSA (署名のみ)
   (7) DSA (機能をあなた自身で設定)
   (8) RSA (機能をあなた自身で設定)
   (9) ECC  ECC
  (10) ECC (署名のみ)
  (11) ECC (機能をあなた自身で設定)
  (13) 既存の鍵
  (14) カードに存在する鍵
あなたの選択は? 11

 続いて鍵の機能を設定します。デフォルトの認められた操作はSignCertifyの2つで、署名機能を無効にするたsで反転させます。

ECDSA/EdDSAに認められた操作: Sign Certify Authenticate
現在の認められた操作: Sign Certify

   (S) 署名機能を反転する
   (A) 認証機能を反転する
   (Q) 完了

あなたの選択は? s

 認められた操作がCertifyだけになったのでqで完了します。

ECDSA/EdDSAに認められた操作: Sign Certify Authenticate
現在の認められた操作: Certify

   (S) 署名機能を反転する
   (A) 認証機能を反転する
   (Q) 完了

あなたの選択は? q

 次に楕円曲線を選択します。強度や処理速度など考慮して好きな曲線を選択してください。マスター鍵はサブ鍵作成時しか使わないので、私は強度の高いNIST P-521(鍵長521bits、強度256bits)を選択しました。

ご希望の楕円曲線を選択してください:
   (1) Curve 25519
   (3) NIST P-256
   (4) NIST P-384
   (5) NIST P-521
   (6) Brainpool P-256
   (7) Brainpool P-384
   (8) Brainpool P-512
   (9) secp256k1
あなたの選択は? 5

 次に鍵の有効期限を設定します。マスター鍵なので無期限にしました。本当ならマスター鍵も有効期限設定するのが正しいのかもしれませんが……

鍵の有効期限を指定してください。
         0 = 鍵は無期限
      <n>  = 鍵は n 日間で期限切れ
      <n>w = 鍵は n 週間で期限切れ
      <n>m = 鍵は n か月間で期限切れ
      <n>y = 鍵は n 年間で期限切れ
鍵の有効期間は? (0)

鍵は無期限です
これで正しいですか? (y/N) y

 続いてユーザー情報を入力します。入力し終わったらoでOKします。
「おいおい名前とメールアドレス晒して大丈夫かよ!」と思われるかもしれませんが、いまさらです。そもそもQiitaで名前晒してますし、GitHubなどでパブリックなリポジトリーを公開したらばれることです。

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

本名: Hirofumi Akiyama
電子メール・アドレス: cocoabreak.git@gmail.com
コメント:

次のユーザIDを選択しました:
    "Hirofumi Akiyama <cocoabreak.git@gmail.com>"

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

 OKするとターミナルには次のメッセージが出力されます。またパスフレーズの入力ダイアログが表示されます。

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

 文字化けしてますが、パスフレーズを入力します。マスター鍵なので複雑なものにしておきましょう。

 OKをクリックすると再度同じようなダイアログが表示されるので、もう一度パスフレーズを入力します。
 なお、裏では次のようなメッセージが出力されますが、無視してかまいません。

gpg: AllowSetForegroundWindow(2192) failed: アクセスが拒否されました。

gpg: AllowSetForegroundWindow(1328) failed: アクセスが拒否されました。

 2回目のパスフレーズの入力が終わるとマスター鍵の出来上がりです。

gpg: C:/Users/cocoabreak/scoop/apps/gpg/current/home/trustdb.gpg: 信用データベースができました
gpg: XXXXXXXXXXXXXXXXを究極的に信用するよう記録しました
gpg: ディレクトリ'C:/Users/cocoabreak/scoop/apps/gpg/current/home/openpgp-revocs.d'が作成されました
gpg: 失効証明書を 'C:/Users/cocoabreak/scoop/apps/gpg/current/home/openpgp-revocs.d\ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ.rev' に保管しました。
公開鍵と秘密鍵を作成し、署名しました。

pub   nistp521 2019-12-23 [C]
      ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ
uid                      Hirofumi Akiyama <cocoabreak.git@gmail.com>

 ちなみにZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZはマスキングしてますが公開鍵のフィンガープリントです(したがってマスキングする必要はないです)。
 次にサブ鍵を作成します。

サブ鍵を作成する

 マスター鍵に対してサブ鍵を追加するにはgpg --edit-keyコマンドを使います。マスター鍵と同様にECCを使用するため--expertオプションを追加します。
 コマンドの引数にZZZ~(フィンガープリント)を設定していますが、マスター鍵作成時に指定した名前やメールアドレスでも問題ありません。

PS C:\Users\cocoabreak> gpg --edit-key --expert ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ
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.

gpg: 信用データベースの検査
gpg: marginals needed: 3  completes needed: 1  trust model: pgp
gpg: 深さ: 0  有効性:   1  署名:   0  信用: 0-, 0q, 0n, 0m, 0f, 1u
秘密鍵が利用できます。

sec  nistp521/XXXXXXXXXXXXXXXX
     作成: 2019-12-23  有効期限: 無期限      利用法: C
     信用: 究極          有効性: 究極
[  究極  ] (1). Hirofumi Akiyama <cocoabreak.git@gmail.com>

  次にaddkeyコマンドを入力し、署名機能が使えればよいので10を選択します。 暗号化を行いたいなら12、認証(Authenticate)を使いたいなら11を選択します。

gpg> addkey

ご希望の鍵の種類を選択してください:
   (3) DSA (署名のみ)
   (4) RSA (署名のみ)
   (5) Elgamal (暗号化のみ)
   (6) RSA (暗号化のみ)
   (7) DSA (機能をあなた自身で設定)
   (8) RSA (機能をあなた自身で設定)
  (10) ECC (署名のみ)
  (11) ECC (機能をあなた自身で設定)
  (12) ECC (暗号化のみ)
  (13) 既存の鍵
  (14) カードに存在する鍵
あなたの選択は? 10

 再び楕円曲線の選択になります。サブ鍵は頻繁に使うことになるので、処理速度を優先して鍵長256bits、強度128bitsのCurve 25519にしました(処理速度比較したわけではないですが、NIST P-256も同等程度かと思います)。

ご希望の楕円曲線を選択してください:
   (1) Curve 25519
   (3) NIST P-256
   (4) NIST P-384
   (5) NIST P-521
   (6) Brainpool P-256
   (7) Brainpool P-384
   (8) Brainpool P-512
   (9) secp256k1
あなたの選択は? 1

 サブ鍵の有効期限を設定します。サブ鍵はある程度有効期限を設定した方が良いそうなので、2022/1/3が期限になるように、日数を入力しました。なお、Gpg4winの場合は期限切れの日付を直接設定できます。

鍵の有効期限を指定してください。
         0 = 鍵は無期限
      <n>  = 鍵は n 日間で期限切れ
      <n>w = 鍵は n 週間で期限切れ
      <n>m = 鍵は n か月間で期限切れ
      <n>y = 鍵は n 年間で期限切れ
鍵の有効期間は? (0)741d
鍵は01/03/22 00:14:33 東京 (標準時)で期限切れとなります
これで正しいですか? (y/N) y
本当に作成しますか? (y/N) y

 マスター鍵のパスフレーズを入力します。

 マスター鍵作成時同様、ターミナルにはエラーメッセージが表示されますが、無視します。
 パスフレーズの入力が終わると、署名&認証用サブ鍵が出来上がります。saveコマンドを入力し、鍵を保存してGPGを終了します。

gpg: AllowSetForegroundWindow(3308) failed: アクセスが拒否されました。

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

sec  nistp521/XXXXXXXXXXXXXXXX
     作成: 2019-12-23  有効期限: 無期限      利用法: C
     信用: 究極          有効性: 究極
ssb  ed25519/YYYYYYYYYYYYYYYY
     作成: 2019-12-23  有効期限: 2022-01-02  利用法: S
[  究極  ] (1). Hirofumi Akiyama <cocoabreak.git@gmail.com>

gpg> save

 有効期限、なんかずれてますね……

マスター鍵を安全な場所に退避させ、秘密鍵を削除する

 サブ鍵の作成が終わったら、マスター鍵は安全な場所にコピーします。鍵のありかは先述の通りで、scoopでインストールしている場合、homeフォルダーごと安全な場所にコピーするのが楽でしょう(私はWinRARで暗号化しつつ、リカバリーレコードを追加してコピーしておきました)。
 安全な場所へコピーが終わったら、PCからマスター鍵の秘密鍵を削除します。いったんgpg --with-keygrip --list-keyコマンドを実行し、Keygripを調べます。

PS C:\Users\cocoabreak> gpg --with-keygrip --list-key
C:/Users/cocoabreak/scoop/apps/gpg/current/home/pubring.kbx
------------------------------------------------------
pub   nistp521 2019-12-23 [C]
      ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ
      Keygrip = KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK
uid           [  究極  ] Hirofumi Akiyama <cocoabreak.git@gmail.com>
sub   ed25519 2019-12-23 [S] [有効期限: 2022-01-02]
      Keygrip = XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

 この例ではKeygrip = KKK~の部分がマスター鍵のKeygripになります。
 Keygripが調べ終わったら、いよいよ秘密鍵の削除です。秘密鍵は%HOMEPATH%\scoop\apps\gpg\current\home\private-keys-v1.dにあるので、"Keygripの値.key" というファイルを削除します。
 これでPCの盗難・紛失、マルウェア感染などによるマスター鍵の秘密鍵の流出リスクは減ったかと思います。

(補足)パスフレーズを緩くする

 マスター鍵作成時に使用したパスフレーズは正直覚えられません。私は1Passwordで管理しているのですが、サブ鍵使用時に1Passwordからコピーして……というのは正直面倒なので、サブ鍵はパスフレーズを少し緩くすることにしました。
 まずはgpg --edit-keyを実行します。

PS C:\Users\cocoabreak> gpg --edit-key ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ
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.

秘密副鍵が利用できます。

pub  nistp521/A257F1AE182E4E08
     作成: 2019-12-23  有効期限: 無期限      利用法: C
     信用: 究極          有効性: 究極
ssb  ed25519/B8F173E603CB4E1F
     作成: 2019-12-23  有効期限: 2022-01-02  利用法: S
[  究極  ] (1). Hirofumi Akiyama <cocoabreak.git@gmail.com>

 次に、パスフレーズを変更するためのコマンドpasswdを実行します。

gpg> passwd

 マスター鍵作成時のパスフレーズを聞かれるので入力します。

 続いて新しいパスフレーズを入力します。相変わらず文字化けしています。

 確認用パスフレーズを入力したら、念のためsaveコマンドで保存して終了します。なおマスター鍵の秘密鍵は削除したのでエラーが表示されますが、無視して問題ありません。

gpg:  XXXXXXXXXXXXXXXX/XXXXXXXXXXXXXXXX: パスフレーズの変更エラー: 秘密鍵がありません
gpg: AllowSetForegroundWindow(12876) failed: アクセスが拒否されました。

gpg: AllowSetForegroundWindow(13240) failed: アクセスが拒否されました。

gpg: AllowSetForegroundWindow(9352) failed: アクセスが拒否されました。


gpg> save
鍵は無変更なので更新は不要です。

GitHubに公開鍵を登録する

 鍵の作成が完了したので、GitHubに公開鍵を登録します。GitHubが公開鍵を信頼する仕組みは、この登録手続きを行うことで理解できるかと思います。

公開鍵をエクスポートする

 GitHubに公開鍵を登録するために公開鍵をエクスポートします。コマンドはgpg --export --armorです。標準ではターミナルに出力されますが、ファイルに出力したい場合は-oオプションを追加します。

gpg --export --armor -o mykey.pub

 鍵の準備ができましたので、次はGitHubの設定です。

GitHubに公開鍵を登録する

 GitHubの設定メニューに「SSH and GPG keys」があります。「GPG keys」の「New GPG key」ボタンをクリックして、先ほどエクスポートした公開鍵を登録します。登録が完了すると、鍵の情報が表示されます。

 よく見ると「Unverified」になっていますが、私がGitHubに登録していないメールアドレスを使って鍵を作成したからです。
 「Emails」メニューでメールアドレスを追加し、Verify email addressしましょう。Verifyが終わると「Unverified」が消えます。

 「このGitHubアカウントの人は、公開鍵に設定されたメールアドレスを受信できる」という確認を行う事で本人確認をしています。

 これでGitHubの設定は完了です。

GitLabに公開鍵を登録する

 基本的にGitHubと同じです。GitLabはメニューなどがローカライズされているので「GPG キー」で公開鍵を登録します。先ほどの例のように、メールアドレスのVerifyが済んでいない場合は、Verifyしましょう。

Gitを設定する

 コミット署名を行うには、Gitの設定変更が必要です。

署名に使用する鍵を設定する

 コミット署名に使用する鍵はuser.signingkeyで設定します。指定する鍵のIDはgpg --list-secret-keys --keyid-format LONGコマンドで確認できます。

PS C:\Users\cocoabreak> gpg --list-secret-keys --keyid-format LONG
C:/Users/cocoabreak/scoop/apps/gpg/current/home/pubring.kbx
------------------------------------------------------
sec#  nistp521/YYYYYYYYYYYYYYYY 2019-12-23 [C]
      ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ
uid                 [  究極  ] Hirofumi Akiyama <cocoabreak.git@gmail.com>
ssb   ed25519/XXXXXXXXXXXXXXXX 2019-12-23 [S] [有効期限: 2022-01-02]

 ssbのXXXXXXXXXXXXXXXXが鍵のIDです。
 確認出来たら設定変更します。今回はグローバル設定にしました。

git config --global user.signingkey XXXXXXXXXXXXXXXX

 次に、GPGコマンドのパスを設定します。Git for WindowsのGPGを使う場合は不要ですが、scoopでインストールしたり、Gpg4winを使用する場合は設定します。

 git config --global gpg.program (gcm gpg).Definition

 補足すると、(gcm gpg).Definitionはgpgコマンドのパスを取得するためにPowerShellのコマンドレットを実行しています(Linuxなどのwhichに相当するものです)。

 ターミナルからコミットする際、自動でコミット署名を行いたい場合は次の設定も行います。

git config --global commit.gpgsign true

 やっと署名を付ける準備が整いました。

署名の付け方

 今までは「コミットに署名を付ける」ことにしか触れてませんでしたが、タグに対しても署名を付けることができます。ここからはいくつかのGitクライアントで署名を付けるための方法を紹介します。

Gitコマンドの場合

 Gitのサイトにマニュアルがあります。
 Git のさまざまなツール - 作業内容への署名

コミットに署名を付ける
git commit -a -S -m "signed commit"

 commit.gpgsign=trueの場合は-Sオプションは不要です。

タグに署名を付ける
git tag -s v1.5 -m "my signed 1.5 tag"

 commit.gpgsignの値に限らず-sオプションは必要です。

Visual Studio Codeの場合

コミットに署名を付ける

 Visual Studio Codeの設定画面で「Enable Commit Signing」にチェックを付けます。

 こうすることで、自動的にコミット署名が付きます。

タグに署名を付ける

 2019/12/24現在、Visual Studio Codeでタグを作成してもタグに対して署名は付きません。Gitコマンドに記載した方法で署名を付けます。

GitKrakenの場合

 GitKrakenの場合、設定画面で署名に使用する鍵や自動的に署名を付けるか設定できます。

 これでコミットやタグ作成すると署名が付きます。

GitHubやGitLabの表示サンプル

GitHub

コミット

01-Git-History.png

タグ

01-Git-Tags.png

リリース

01-Git-Releases.png

GitLab

 2019/12/25時点でGitLabはタグに対する署名(の検証)には対応していません。また、リリースページはAPIを使わないと作成できないため、今回は割愛しました。

コミット

02-Git-History.png

最後に

 私になりすます人がどれだけいるかわかりませんが、ちょっとした操作で簡単に署名を付けることができるので、自衛のためにも署名を付けておくのは良いのかなと思います。

おまけ

 今回作成したリポジトリーです。

 GitHub
 GitLab

13
13
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
13