Emacsのパッケージがインストールされるのを眺めるで.sigという拡張子のファイルをダウンロードしていました。これはGnuPGの署名ファイルです。今回はこの署名ファイルの検証をしてみます。また自分で署名ファイルを作成もしてみます。
なお実行環境のOSはmacOS Mojaveです。
おしながき
準備
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を使ってインストールします。
brew install gnupg
インストールされたGnuPGのバージョンを確認します。
gpg --version
出力
gpg (GnuPG) 2.2.13
libgcrypt 1.8.4
Copyright (C) 2019 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 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.
〜省略〜
サポートしているアルゴリズム:
公開鍵: RSA, ELG, DSA, ECDH, ECDSA, EDDSA
暗号方式: IDEA, 3DES, CAST5, BLOWFISH, AES, AES192, AES256,
TWOFISH, CAMELLIA128, CAMELLIA192, CAMELLIA256
ハッシュ: SHA1, RIPEMD160, SHA256, SHA384, SHA512, SHA224
圧縮: 無圧縮, ZIP, ZLIB, BZIP2
gpg-agentのインストール
gpg-agentは秘密鍵を任意のプロトコルから独立して管理します。
https://www.gnupg.org/documentation/manuals/gnupg/Invoking-GPG_002dAGENT.html
brew install gpg-agent
gpgはpgp-agentをバックエンドとして利用されます。gpg-agentのプロセスはgpgなどの起動時に自動的に起動されます。
pinentry-macのインストール
pinentryはGnuPGのパスフレーズやPIN番号を入力する手段を提供するプログラムです。macOSではmacOS用のpinentry-macをインストールするとパスフレーズ入力時などにGUIのダイアログが開くようになります。
Homebrewを使ってインストールします。
brew install pinentry-mac
gpg-agentがpinentry-macを使うための設定
gpg-agentにpinentry-macを利用させるには~/.gnupg/gpg-agent.confに次の設定をします。
use-standard-socket
pinentry-program /usr/local/bin/pinentry-mac
設定が完了したら設定を読み込ませるためにgpg-agentを一度終了します。
gpgconf --kill all
鍵を作成する
自分の鍵を作成してみます。作成には --gen-key
オプションを指定します。通常はインタラクティブな画面上のやりとりが必要ですが --batch
を指定することで設定ファイルからも鍵を生成できます。
master.confの中身
# プライマリキー
Key-Type: RSA
Key-Length: 4096
# サブキー
Subkey-Type: RSA
Subkey-Length: 4096
# プライマリキー及びサブキーの有効期間を1ヶ月に設定
Expire-Date: 1m
# 名前とメールアドレスを設定
Name-Real: sximada
Name-Email: 50688746+sximada@users.noreply.github.com
# パスフレーズを設定 (大文字小文字・数字・記号を混ぜた安全なパスフレーズを指定してください)
Passphrase: xxxxxxxxxxx
# 上記の内容で鍵ペアを作成
%commit
%echo Successfully done
設定ファイルの詳しい書き方はhttps://www.gnupg.org/documentation/manuals/gnupg/Unattended-GPG-key-generation.htmlに書かれています。
では鍵を生成します。
gpg --gen-key --batch master.conf
出力
gpg: 鍵3DEB51DB0CA60F0Aを究極的に信用するよう記録しました
gpg: ディレクトリ'/Users/xxx/.gnupg/openpgp-revocs.d'が作成されました
gpg: 失効証明書を '/Users/xxx/.gnupg/openpgp-revocs.d/27621C5B18388278B335B3903DEB51DB0CA60F0A.rev' に保管しました。
gpg: Successfully done
生成に成功したようです。master.confの設定にしたがって鍵が作成されました。/Users/xxx/.gnupg/openpgp-revocs.d
に出力されたのは失効証明書です。秘密鍵が漏れたなどの理由で鍵の失効をしなくてはいけなくなった時に使います。
署名を検証する
前回確認したarchive-contentsの署名を確認します。まずはarchive-contentsファイルとその署名ファイルをelpaからダウンロードします。
curl https://elpa.gnu.org//packages/archive-contents -o archive-contents
curl https://elpa.gnu.org//packages/archive-contents.sig -o archive-contents.sig
ファイル名 | 説明 |
---|---|
archive-contents | elpaのindex情報 |
archive-contents.sig | archive-contentsの署名 |
ではこの署名を検証します。 --verify
と署名ファイルを指定します。署名対象のファイルも指定できますが省略した場合は.sig拡張子が取られた状態のファイルを対象にします。
gpg --verify archive-contents.sig
出力
gpg: 署名されたデータが'archive-contents'にあると想定します
gpg: 金 5/17 06:10:03 2019 JSTに施された署名
gpg: DSA鍵CA442C00F91774F17F59D9B0474F05837FBDEF9Bを使用
gpg: 署名を検査できません: No public key
署名の検査に失敗しました。 No public key
と出力されています。署名の検証には公開鍵を使いますがそれがないようです。署名に使用された鍵は CA442C00F91774F17F59D9B0474F05837FBDEF9B
です。この鍵を探してみます。鍵の検索には --search-key
と探す鍵を指定します。
gpg --search-key CA442C00F91774F17F59D9B0474F05837FBDEF9B
鍵が見つかるとその情報が表示されます。鍵の番号を入力しエンターを押すと鍵がインポートされます。
gpg: data source: https://51.38.91.189:443
(1) GNU ELPA Signing Agent <elpasign@elpa.gnu.org>
GNU ELPA Signing Agent (2014) <elpasign@elpa.gnu.org>
2048 bit DSA key 474F05837FBDEF9B, 作成: 2014-09-24, 有効期限: 2019-09-23
Keys 1-1 of 1 for "CA442C00F91774F17F59D9B0474F05837FBDEF9B". 番号(s)、N)次、またはQ)中止を入力してください >1
gpg: 鍵474F05837FBDEF9B: 公開鍵"GNU ELPA Signing Agent (2014) <elpasign@elpa.gnu.org>"をインポートしました
gpg: 処理数の合計: 1
gpg: インポート: 1
インポートされた鍵を確認します。鍵の一覧を確認するには -k
を指定します。
gpg -k
出力
/Users/xxx/.gnupg/pubring.kbx
---------------------------------
pub rsa4096 2019-05-17 [SCEA] [有効期限: 2019-06-16]
2762 1C5B 1838 8278 B335 B390 3DEB 51DB 0CA6 0F0A
uid [ 究極 ] sximada <50688746+sximada@users.noreply.github.com>
sub rsa4096 2019-05-17 [SEA] [有効期限: 2019-06-16]
pub dsa2048 2014-09-24 [SC] [有効期限: 2019-09-23]
CA44 2C00 F917 74F1 7F59 D9B0 474F 0583 7FBD EF9B
uid [ 不明 ] GNU ELPA Signing Agent (2014) <elpasign@elpa.gnu.org>
uid [ 不明 ] GNU ELPA Signing Agent <elpasign@elpa.gnu.org>
再度署名を検証します。
gpg --verify archive-contents.sig
出力
gpg: 署名されたデータが'archive-contents'にあると想定します
gpg: 金 5/17 06:10:03 2019 JSTに施された署名
gpg: DSA鍵CA442C00F91774F17F59D9B0474F05837FBDEF9Bを使用
gpg: "GNU ELPA Signing Agent (2014) <elpasign@elpa.gnu.org>"からの正しい署名 [不明の]
gpg: 別名"GNU ELPA Signing Agent <elpasign@elpa.gnu.org>" [不明の]
gpg: *警告*: この鍵は信用できる署名で証明されていません!
gpg: この署名が所有者のものかどうかの検証手段がありません。
主鍵フィンガープリント: CA44 2C00 F917 74F1 7F59 D9B0 474F 0583 7FBD EF9B
先ほどインポートした公開鍵が信用できるものとして登録されていないので警告が出ます。鍵の信用を設定するためには --edit-key
オプションを使います。
gpg --edit-key CA442C00F91774F17F59D9B0474F05837FBDEF9B
コマンドを実行するとインタラクティブに操作を求めてきます。trustコマンドを実行し公開鍵の信用を設定します。
gpg (GnuPG) 2.2.13; 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 dsa2048/474F05837FBDEF9B
作成: 2014-09-24 有効期限: 2019-09-23 利用法: SC
信用: 不明の 有効性: 不明の
[ 不明 ] (1). GNU ELPA Signing Agent (2014) <elpasign@elpa.gnu.org>
[ 不明 ] (2) GNU ELPA Signing Agent <elpasign@elpa.gnu.org>
gpg> trust
pub dsa2048/474F05837FBDEF9B
作成: 2014-09-24 有効期限: 2019-09-23 利用法: SC
信用: 不明の 有効性: 不明の
[ 不明 ] (1). GNU ELPA Signing Agent (2014) <elpasign@elpa.gnu.org>
[ 不明 ] (2) GNU ELPA Signing Agent <elpasign@elpa.gnu.org>
他のユーザの鍵を正しく検証するために、このユーザの信用度を決めてください
(パスポートを見せてもらったり、他から得たフィンガープリントを検査したり、などなど)
1 = 知らない、または何とも言えない
2 = 信用し ない
3 = まぁまぁ信用する
4 = 充分に信用する
5 = 究極的に信用する
m = メーン・メニューに戻る
あなたの決定は? 5
本当にこの鍵を究極的に信用しますか? (y/N) y
pub dsa2048/474F05837FBDEF9B
作成: 2014-09-24 有効期限: 2019-09-23 利用法: SC
信用: 究極 有効性: 不明の
[ 不明 ] (1). GNU ELPA Signing Agent (2014) <elpasign@elpa.gnu.org>
[ 不明 ] (2) GNU ELPA Signing Agent <elpasign@elpa.gnu.org>
プログラムを再起動するまで、表示された鍵の有効性は正しくないかもしれない、
ということを念頭においてください。
gpg> quit
再度署名の検証を行います。
gpg --verify archive-contents.sig
出力
gpg: 署名されたデータが'archive-contents'にあると想定します
gpg: 金 5/17 06:10:03 2019 JSTに施された署名
gpg: DSA鍵CA442C00F91774F17F59D9B0474F05837FBDEF9Bを使用
gpg: 信用データベースの検査
gpg: marginals needed: 3 completes needed: 1 trust model: pgp
gpg: 深さ: 0 有効性: 2 署名: 0 信用: 0-, 0q, 0n, 0m, 0f, 2u
gpg: 次回の信用データベース検査は、2019-06-16です
gpg: "GNU ELPA Signing Agent (2014) <elpasign@elpa.gnu.org>"からの正しい署名 [究極]
gpg: 別名"GNU ELPA Signing Agent <elpasign@elpa.gnu.org>" [究極]
今回は署名の検証が成功しました。
署名を作成する
今度はファイルに対して署名を作成してみます。署名を作るファイルはこのような内容のテキストファイルにします。
!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
gpg --detach-sign test.txt
実行するとパスフレーズを入力するためのダイアログが表示されます。
正しいパスフレーズを入力するとtest.txt.sigが作成されます。
作成した署名を確認するには以前と同様 --verity
を使って.sigファイルを指定します。
gpg --verify test.txt.sig
出力はこのように変わります。
gpg: 署名されたデータが'test.txt'にあると想定します
gpg: 金 5/17 18:47:59 2019 JSTに施された署名
gpg: RSA鍵656F942AE22C3745399E2AF875C619F5A386C062を使用
gpg: "sximada <50688746+sximada@users.noreply.github.com>"からの正しい署名 [究極]
適切に署名ができていることがわかります。
公開鍵を公開する
誰かにこの署名を検証してもらうためには自分の公開鍵を渡します。公開鍵をエクスポートしてWeb上のどこかに置いておくか、またはPGP公開鍵サーバーに公開鍵をアップロードするという方法もあります。
公開鍵をエクスポートする
公開鍵をWeb上に配置するにせよ誰かに渡すにせよ、GnuPGが内部的に管理している状態では渡すこともできず不便です。 --export
を使って公開鍵を出力してそれを渡します。
gpg --export --armor
このテキストが公開鍵ですので必要に応じてこれを渡せばば良いです。逆にインポートは --import FILENAME
で取り込めます。
PGP公開鍵サーバーに公開鍵をアップロードする
より多くの人に使ってもらいたい場合はPGP公開鍵サーバーに公開鍵をアップロードするほうが好ましいかもしれません。PGP公開鍵サーバーを使うことで何が嬉しいかというと、鍵の検索やインポートをgpgコマンドのみでできるというところです。
鍵の一覧を確認します。
gpg -k
--keyserver
で送信するサーバーを指定し --send-keys
で送信する鍵を指定します。コマンドはこのようになります。今回は継続使うものではないので送信はしませんでした。
gpg --keyserver pgp.mit.edu --send-keys 27621C5B18388278B335B3903DEB51DB0CA60F0A
公開鍵は送信すると削除はできません(失効は失効証明書を使うことで可能です)。
まとめ
以下のことを実施しました。
- GnuPGとは何かを説明し、使用できる環境を作成した
- 自分の鍵を作成しどこのディレクトリに配置されたのかを確認した
- 署名を検証した実際のデータ(elpaのインデックス情報)を使って学んだ
- 自分の鍵を使用してファイルを署名する手順を学んだ
- 自分の公開鍵を公開する方法を学んだ
GnuPGを扱う上でだいたい一通りのことを今回実施しました。使い方はとっつきにくいですが慣れればそれほどでもないので色々と触ってみると良いかもしせません。
参考
- gpgでのファイルの暗号化基礎 - akihiroobの日記
- GPG Cheat Sheet
- OpenPGP Keyserver
- PGP KEYSERVER
- 1分でわかるPGP - 村川猛彦
- GnuPGのコマンド
- GnuPGを使用したファイル署名の検証
- Getting Started with Gnu Privacy Guard
- macOS で GitHub に GPG で署名する - プらチナの日記
- GnuPG で遊ぶ - 暗号化してみる | そんなこと覚えてない
- GNU Hello - Wikipedia
- Failed to fetch the gpg key from keys.gnupg.net · Issue #3544 · rvm/rvm · GitHub
- GnuPG - Signature Key
- Bitcoinいれるならgpg を理解せよ – 暗号通貨 とセキュリティ – Medium
- PGP(GnuPG)の導入方法教えてやるから、いい加減、ファイルをZIP暗号化して、別メールでパスワードを送るのは、やめてくれ! ~ファイル添付編~ - Qiita
- PGP(GnuPG)の導入方法教えてやるから、いい加減、ファイルをZIP暗号化して、別メールでパスワードを送るのは、やめてくれ! ~セットアップ編~ - Qiita
- gpg (GNU Privacy Guard)の使い方 - Qiita
- git(GitHub)でGPGを使った署名をおこなう - Qiita
- hello - GNU greeting package - News: hello-2.10 released
- GNU Hello 2.5 の導入 - とくにあぶなくないRiSKのブログ
- gnupg - where can I find the public key for Gnu Emacs? - Stack Overflow
- OpenPGP 鍵管理に関する考察 — OpenPGP の実装 | text.Baldanders.info
- GnuPG for Windows : gpg-agent について — OpenPGP の実装 | text.Baldanders.info
- configure と GnuPG について - その時々
- GnuPG - ArchWiki
- ダウンロードファイルが真正なものであるかを確認:仕事で使える魔法のLAMP(10) - @IT
- GnuPGの署名を確認する
- Hello - GNU Project - Free Software Foundation
- gnUSENET - GNU Project - Free Software Foundation
- gnUSENET - GNU Project - Free Software Foundation
- Using the GNU Privacy Guard: Invoking GPG-AGENT
- Where is GNU's public key?
- GPG でファイルを暗号化, 復号化, 署名, 検証する方法 - yu8mada
- Homebrew で macOS に GNU コマンドをインストールする - yu8mada
この記事へのコメント