そして粛々と生きる

Emacsのパッケージがインストールされるのを眺めるで.sigという拡張子のファイルをダウンロードしていました。これはGnuPGの署名ファイルです。今回はこの署名ファイルの検証をしてみます。また自分で署名ファイルを作成もしてみます。

なお実行環境のOSはmacOS Mojaveです。

おしながき

  1. 準備
    1. GnuPGとは
    2. GnuPGのインストール
    3. gpg-agentのインストール
    4. pinentry-macのインストール
    5. gpg-agentがpinentry-macを使うための設定
  2. 鍵を作成する
  3. 署名を検証する
  4. 署名を作成する
  5. 公開鍵を公開する
    1. 公開鍵をエクスポートする
    2. PGP公開鍵サーバーに公開鍵をアップロードする
  6. まとめ
  7. 参考

準備

GnuPGとは

GNU Privacy Guard (GnuPG, GPG) とは、Pretty Good Privacy (PGP) の別実装として、GPL に基づいた暗号化ソフトである。 OpenPGP 規格 (RFC 4880) に完全準拠しているが、古い PGP との互換性は完全ではない。
(Wikipediaより: GNU Privacy Guard - https://ja.wikipedia.org/wiki/GNU_Privacy_Guard)

要は暗号化や署名といった機能を提供します。誰かにデータを渡したり渡されたりする際、データの中身を見られないようにしたり、そのデータが本当に本人から渡されたことを保証するためのツールです。様々な場面で使われていますが、例えばパッケージ管理ツールはPGPの機構を利用してダウンロードしたファイルを検証しています。

GnuPGのインストール

今回はHomebrewを使ってインストールします。

  1. brew install gnupg

インストールされたGnuPGのバージョンを確認します。

  1. gpg --version

出力

  1. gpg (GnuPG) 2.2.13
  2. libgcrypt 1.8.4
  3. Copyright (C) 2019 Free Software Foundation, Inc.
  4. License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>
  5. This is free software: you are free to change and redistribute it.
  6. There is NO WARRANTY, to the extent permitted by law.
  7. 〜省略〜
  8. サポートしているアルゴリズム:
  9. 公開鍵: RSA, ELG, DSA, ECDH, ECDSA, EDDSA
  10. 暗号方式: IDEA, 3DES, CAST5, BLOWFISH, AES, AES192, AES256,
  11. TWOFISH, CAMELLIA128, CAMELLIA192, CAMELLIA256
  12. ハッシュ: SHA1, RIPEMD160, SHA256, SHA384, SHA512, SHA224
  13. 圧縮: 無圧縮, ZIP, ZLIB, BZIP2

gpg-agentのインストール

gpg-agentは秘密鍵を任意のプロトコルから独立して管理します。

https://www.gnupg.org/documentation/manuals/gnupg/Invoking-GPG_002dAGENT.html

  1. brew install gpg-agent

gpgはpgp-agentをバックエンドとして利用されます。gpg-agentのプロセスはgpgなどの起動時に自動的に起動されます。

pinentry-macのインストール

pinentryはGnuPGのパスフレーズやPIN番号を入力する手段を提供するプログラムです。macOSではmacOS用のpinentry-macをインストールするとパスフレーズ入力時などにGUIのダイアログが開くようになります。

Homebrewを使ってインストールします。

  1. brew install pinentry-mac

gpg-agentがpinentry-macを使うための設定

gpg-agentにpinentry-macを利用させるには~/.gnupg/gpg-agent.confに次の設定をします。

  1. use-standard-socket
  2. pinentry-program /usr/local/bin/pinentry-mac

設定が完了したら設定を読み込ませるためにgpg-agentを一度終了します。

  1. gpgconf --kill all

鍵を作成する

自分の鍵を作成してみます。作成には --gen-key オプションを指定します。通常はインタラクティブな画面上のやりとりが必要ですが --batch を指定することで設定ファイルからも鍵を生成できます。

master.confの中身

  1. # プライマリキー
  2. Key-Type: RSA
  3. Key-Length: 4096
  4. # サブキー
  5. Subkey-Type: RSA
  6. Subkey-Length: 4096
  7. # プライマリキー及びサブキーの有効期間を1ヶ月に設定
  8. Expire-Date: 1m
  9. # 名前とメールアドレスを設定
  10. Name-Real: sximada
  11. Name-Email: 50688746+sximada@users.noreply.github.com
  12. # パスフレーズを設定 (大文字小文字・数字・記号を混ぜた安全なパスフレーズを指定してください)
  13. Passphrase: xxxxxxxxxxx
  14. # 上記の内容で鍵ペアを作成
  15. %commit
  16. %echo Successfully done

設定ファイルの詳しい書き方はhttps://www.gnupg.org/documentation/manuals/gnupg/Unattended-GPG-key-generation.htmlに書かれています。

では鍵を生成します。

  1. gpg --gen-key --batch master.conf

出力

  1. gpg: 3DEB51DB0CA60F0Aを究極的に信用するよう記録しました
  2. gpg: ディレクトリ'/Users/xxx/.gnupg/openpgp-revocs.d'が作成されました
  3. gpg: 失効証明書を '/Users/xxx/.gnupg/openpgp-revocs.d/27621C5B18388278B335B3903DEB51DB0CA60F0A.rev' に保管しました。
  4. gpg: Successfully done

生成に成功したようです。master.confの設定にしたがって鍵が作成されました。
/Users/xxx/.gnupg/openpgp-revocs.d に出力されたのは失効証明書です。秘密鍵が漏れたなどの理由で鍵の失効をしなくてはいけなくなった時に使います。

署名を検証する

前回確認したarchive-contentsの署名を確認します。まずはarchive-contentsファイルとその署名ファイルをelpaからダウンロードします。

  1. curl https://elpa.gnu.org//packages/archive-contents -o archive-contents
  2. curl https://elpa.gnu.org//packages/archive-contents.sig -o archive-contents.sig
ファイル名 説明
archive-contents elpaのindex情報
archive-contents.sig archive-contentsの署名

ではこの署名を検証します。 --verify と署名ファイルを指定します。署名対象のファイルも指定できますが省略した場合は.sig拡張子が取られた状態のファイルを対象にします。

  1. gpg --verify archive-contents.sig

出力

  1. gpg: 署名されたデータが'archive-contents'にあると想定します
  2. gpg: 5/17 06:10:03 2019 JSTに施された署名
  3. gpg: DSACA442C00F91774F17F59D9B0474F05837FBDEF9Bを使用
  4. gpg: 署名を検査できません: No public key

署名の検査に失敗しました。 No public key と出力されています。署名の検証には公開鍵を使いますがそれがないようです。署名に使用された鍵は CA442C00F91774F17F59D9B0474F05837FBDEF9B です。この鍵を探してみます。鍵の検索には --search-key と探す鍵を指定します。

  1. gpg --search-key CA442C00F91774F17F59D9B0474F05837FBDEF9B

鍵が見つかるとその情報が表示されます。鍵の番号を入力しエンターを押すと鍵がインポートされます。

  1. gpg: data source: https://51.38.91.189:443
  2. (1) GNU ELPA Signing Agent <elpasign@elpa.gnu.org>
  3. GNU ELPA Signing Agent (2014) <elpasign@elpa.gnu.org>
  4. 2048 bit DSA key 474F05837FBDEF9B, 作成: 2014-09-24, 有効期限: 2019-09-23
  5. Keys 1-1 of 1 for "CA442C00F91774F17F59D9B0474F05837FBDEF9B". 番号(s)、N)次、またはQ)中止を入力してください >1
  6. gpg: 474F05837FBDEF9B: 公開鍵"GNU ELPA Signing Agent (2014) <elpasign@elpa.gnu.org>"をインポートしました
  7. gpg: 処理数の合計: 1
  8. gpg: インポート: 1

インポートされた鍵を確認します。鍵の一覧を確認するには -k を指定します。

  1. gpg -k

出力

  1. /Users/xxx/.gnupg/pubring.kbx
  2. ---------------------------------
  3. pub rsa4096 2019-05-17 [SCEA] [有効期限: 2019-06-16]
  4. 2762 1C5B 1838 8278 B335 B390 3DEB 51DB 0CA6 0F0A
  5. uid [ 究極 ] sximada <50688746+sximada@users.noreply.github.com>
  6. sub rsa4096 2019-05-17 [SEA] [有効期限: 2019-06-16]
  7. pub dsa2048 2014-09-24 [SC] [有効期限: 2019-09-23]
  8. CA44 2C00 F917 74F1 7F59 D9B0 474F 0583 7FBD EF9B
  9. uid [ 不明 ] GNU ELPA Signing Agent (2014) <elpasign@elpa.gnu.org>
  10. uid [ 不明 ] GNU ELPA Signing Agent <elpasign@elpa.gnu.org>

再度署名を検証します。

  1. gpg --verify archive-contents.sig

出力

  1. gpg: 署名されたデータが'archive-contents'にあると想定します
  2. gpg: 5/17 06:10:03 2019 JSTに施された署名
  3. gpg: DSACA442C00F91774F17F59D9B0474F05837FBDEF9Bを使用
  4. gpg: "GNU ELPA Signing Agent (2014) <elpasign@elpa.gnu.org>"からの正しい署名 [不明の]
  5. gpg: 別名"GNU ELPA Signing Agent <elpasign@elpa.gnu.org>" [不明の]
  6. gpg: *警告*: この鍵は信用できる署名で証明されていません!
  7. gpg: この署名が所有者のものかどうかの検証手段がありません。
  8. 主鍵フィンガープリント: CA44 2C00 F917 74F1 7F59 D9B0 474F 0583 7FBD EF9B

先ほどインポートした公開鍵が信用できるものとして登録されていないので警告が出ます。鍵の信用を設定するためには --edit-key オプションを使います。

  1. gpg --edit-key CA442C00F91774F17F59D9B0474F05837FBDEF9B

コマンドを実行するとインタラクティブに操作を求めてきます。trustコマンドを実行し公開鍵の信用を設定します。

  1. gpg (GnuPG) 2.2.13; Copyright (C) 2019 Free Software Foundation, Inc.
  2. This is free software: you are free to change and redistribute it.
  3. There is NO WARRANTY, to the extent permitted by law.
  4. pub dsa2048/474F05837FBDEF9B
  5. 作成: 2014-09-24 有効期限: 2019-09-23 利用法: SC
  6. 信用: 不明の 有効性: 不明の
  7. [ 不明 ] (1). GNU ELPA Signing Agent (2014) <elpasign@elpa.gnu.org>
  8. [ 不明 ] (2) GNU ELPA Signing Agent <elpasign@elpa.gnu.org>
  9. gpg> trust
  10. pub dsa2048/474F05837FBDEF9B
  11. 作成: 2014-09-24 有効期限: 2019-09-23 利用法: SC
  12. 信用: 不明の 有効性: 不明の
  13. [ 不明 ] (1). GNU ELPA Signing Agent (2014) <elpasign@elpa.gnu.org>
  14. [ 不明 ] (2) GNU ELPA Signing Agent <elpasign@elpa.gnu.org>
  15. 他のユーザの鍵を正しく検証するために、このユーザの信用度を決めてください
  16. (パスポートを見せてもらったり、他から得たフィンガープリントを検査したり、などなど)
  17. 1 = 知らない、または何とも言えない
  18. 2 = 信用し ない
  19. 3 = まぁまぁ信用する
  20. 4 = 充分に信用する
  21. 5 = 究極的に信用する
  22. m = メーン・メニューに戻る
  23. あなたの決定は? 5
  24. 本当にこの鍵を究極的に信用しますか? (y/N) y
  25. pub dsa2048/474F05837FBDEF9B
  26. 作成: 2014-09-24 有効期限: 2019-09-23 利用法: SC
  27. 信用: 究極 有効性: 不明の
  28. [ 不明 ] (1). GNU ELPA Signing Agent (2014) <elpasign@elpa.gnu.org>
  29. [ 不明 ] (2) GNU ELPA Signing Agent <elpasign@elpa.gnu.org>
  30. プログラムを再起動するまで、表示された鍵の有効性は正しくないかもしれない、
  31. ということを念頭においてください。
  32. gpg> quit

再度署名の検証を行います。

  1. gpg --verify archive-contents.sig

出力

  1. gpg: 署名されたデータが'archive-contents'にあると想定します
  2. gpg: 5/17 06:10:03 2019 JSTに施された署名
  3. gpg: DSACA442C00F91774F17F59D9B0474F05837FBDEF9Bを使用
  4. gpg: 信用データベースの検査
  5. gpg: marginals needed: 3 completes needed: 1 trust model: pgp
  6. gpg: 深さ: 0 有効性: 2 署名: 0 信用: 0-, 0q, 0n, 0m, 0f, 2u
  7. gpg: 次回の信用データベース検査は、2019-06-16です
  8. gpg: "GNU ELPA Signing Agent (2014) <elpasign@elpa.gnu.org>"からの正しい署名 [究極]
  9. gpg: 別名"GNU ELPA Signing Agent <elpasign@elpa.gnu.org>" [究極]

今回は署名の検証が成功しました。

署名を作成する

今度はファイルに対して署名を作成してみます。署名を作るファイルはこのような内容のテキストファイルにします。

!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~

  1. gpg --detach-sign test.txt

実行するとパスフレーズを入力するためのダイアログが表示されます。

正しいパスフレーズを入力するとtest.txt.sigが作成されます。

作成した署名を確認するには以前と同様 --verity を使って.sigファイルを指定します。

  1. gpg --verify test.txt.sig

出力はこのように変わります。

  1. gpg: 署名されたデータが'test.txt'にあると想定します
  2. gpg: 5/17 18:47:59 2019 JSTに施された署名
  3. gpg: RSA656F942AE22C3745399E2AF875C619F5A386C062を使用
  4. gpg: "sximada <50688746+sximada@users.noreply.github.com>"からの正しい署名 [究極]

適切に署名ができていることがわかります。

公開鍵を公開する

誰かにこの署名を検証してもらうためには自分の公開鍵を渡します。公開鍵をエクスポートしてWeb上のどこかに置いておくか、またはPGP公開鍵サーバーに公開鍵をアップロードするという方法もあります。

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

公開鍵をWeb上に配置するにせよ誰かに渡すにせよ、GnuPGが内部的に管理している状態では渡すこともできず不便です。 --export を使って公開鍵を出力してそれを渡します。

  1. gpg --export --armor

このテキストが公開鍵ですので必要に応じてこれを渡せばば良いです。逆にインポートは --import FILENAME で取り込めます。

PGP公開鍵サーバーに公開鍵をアップロードする

より多くの人に使ってもらいたい場合はPGP公開鍵サーバーに公開鍵をアップロードするほうが好ましいかもしれません。PGP公開鍵サーバーを使うことで何が嬉しいかというと、鍵の検索やインポートをgpgコマンドのみでできるというところです。

鍵の一覧を確認します。

  1. gpg -k

--keyserver で送信するサーバーを指定し --send-keys で送信する鍵を指定します。コマンドはこのようになります。今回は継続使うものではないので送信はしませんでした。

  1. gpg --keyserver pgp.mit.edu --send-keys 27621C5B18388278B335B3903DEB51DB0CA60F0A

公開鍵は送信すると削除はできません(失効は失効証明書を使うことで可能です)。

まとめ

以下のことを実施しました。

  • GnuPGとは何かを説明し、使用できる環境を作成した
  • 自分の鍵を作成しどこのディレクトリに配置されたのかを確認した
  • 署名を検証した実際のデータ(elpaのインデックス情報)を使って学んだ
  • 自分の鍵を使用してファイルを署名する手順を学んだ
  • 自分の公開鍵を公開する方法を学んだ

GnuPGを扱う上でだいたい一通りのことを今回実施しました。使い方はとっつきにくいですが慣れればそれほどでもないので色々と触ってみると良いかもしせません。

参考

この記事へのコメント

まだコメントはありません