GPG 入門
GPG 入門
GnuPG は、Pretty Good Privacy (PGP) のOSS版です。
GNU Privacy Guard (GnuPG, GPGはOpenPGP標準の実装。以下のことを行います。
暗号化
電子署名
公開鍵認証
例えば、パッケージマネージャーなどのインストーラーがダウンロードするソフトウェアが意図した作成者が作成したものであるか確認してからインストールします。これを実現する仕組みの一つです。 鍵管理には、公開鍵方式を使用しますが、認証局を設置せず、ユーザーそれぞれが鍵管理をして、取得した公開鍵を確認します。
GPGでは、以下の2つの秘密鍵を作ります。
署名のためのmaster key
署名に加えて暗号化を行うためのsub key
master keyは絶対に流出させないように厳重に管理し、普段の運用にsub keyを使用する。
master keyを使用するのは以下の場合です(参照: *** GPGで自分用の秘密鍵を1つに統一する)。
他人の鍵に署名
鍵を取り消し
UIDを強く信頼
新しいsub keyを作成
他の鍵の暗号化アルゴリズム、ハッシュ関数などを変更
鍵の有効期限を指定
master keyは、オフライン環境で、一度もネットワークに繋いだことのないOSのような環境で実行し、厳重に管理します。信頼できない、OS上では実行してはいけない。 署名と暗号化に同一の鍵を使うと、暗号化アルゴリズム依存の脆弱性が生じる場合があるので、暗号化、署名、認証のそれぞれに専用のsub keyを作ると良い。
Web of Trust
公開鍵の正当性を確認するために、フィンガープリントが一致していることを確認します。正当性の確認が済んだ後,受け取った公開鍵に,自分の秘密鍵で署名することで準備完了です。
信頼できる人が信頼している公開鍵は信用することを、広げていきます。このように、互いに、鍵の署名を行いあうことで、信頼の関係を構築していくことで、信頼関係を構築します。 公開鍵の正当性の確認を行わないと、Web of Trust全体の信頼性が下がります。
自身の鍵ペアについては、公開鍵はWeb上で公開したり、鍵サーバーに登録し、メールを送る都度添付することで対応します。他の人は自身あてに暗号化メールを送ったり、他の人が自身の公開鍵で自身が署名した内容を検証できるようになります。
これらの公開鍵をまとめておくものが鍵束(Keyring)です。これは以下のようにバイナリーファイルとして格納されています。
ただし、公開鍵は普段使いには、サイズが大きいため、電子指紋(鍵指紋)をメールのヘッダーやフッターに添付することで、Web上に公開しておいた公開鍵の電子指紋と比較することができる。
gpgコマンドの使い方
環境
以下のバージョンで検証。
GPGのバージョンは以下。
RPMのバージョンは以下。
Get Started
GPG鍵の生成
GPG鍵を生成。鍵の種類や有効期限などを聞かれるがここではすべてデフォルトのまま使用する。
以下のような画面でパスフレーズを入力します。
インポートされている公開鍵の情報は以下。
なお、上記コマンドの初回実行時は以下のようなデバッグメッセージが出力されるので、自動化の際は注意。
GPGで暗号化、署名
まず、GPGはどのように扱うか基本を抑えておく必要がある。
ファイルの署名には以下のコマンドを実行します。
以下のような入力画面が出てくるので、鍵作成時に指定したパスワードを入力します。
すると、以下のようなバイナリーファイルが作成されます。
-aオプションを使用することで、テキスト形式でファイルが出力されます。
元のデータを残した状態で署名するには以下のように実行します。
元のデータとは別に署名用のファイルを作成する場合は以下のように実行します。すると、バイナリ形式の署名ファイルが生成されます。
先程同様に-aオプションを付与することで、テキスト形式で署名ファイルを生成します。
署名を検証。署名ファイルと同じディレクトリに元のファイルがあることを前提としている。
ここで、ファイル名を変更してみます。
すると、データがないものと認識されてしまいます。
引数に変更後のファイル名を指定すると、正常に署名を検証できます。
References
RPMでGPG署名
RPMパッケージの作成
RPMパッケージにGPGで署名する前に、簡単なRPMファイルを作成しておく。
以下、Amazon Linux 2での検証です。CentOS 7でもおおよそ同様に検証できるでしょう。 RPM環境のセットアップと、目的のアプリケーションの用意。
以下の内容でSpecファイルを作成
rpmの作成 + インストール。
結果確認。
SSHでログイン時にも反映されていることを確認。
作成されたパッケージは以下のように、Signatureがnoneより無署名状態。
References
カスタムRPMや独自yumリポジトリではじめるソフトウェア管理術 !!
Notes
specファイルの作成からgpgの署名方法など
実際にRPMに対してgpgで署名(ファイルに対する署名)
署名を付加するのに必要なライブラリをインストール。
署名の状態を確認する。
署名を付加する。
raw RPM マクロ定義、すなわち、上記署名は以下のデフォルト値が適用されている。後ほどカスタムマクロを用いてGPGの設定を編集する。
GPGの署名も有効であることが確認できる。
以下でも署名が有効であることが確認できる。
Signatureも付加されている。
.gnupg/以下には以下のようなファイルが生成されている。
カスタムマクロファイル
GPGの設定を先程は、デフォルト設定で署名したが、設定した値で署名する。
そのためにカスタムマクロファイルを作成。custom_rpm.macrosという名前で以下のファイルを作成
以下のように実行
署名されていることが確認できる。
References
Notes
rpmにGPGで署名する方法が端的にまとまっている。
Notes
コマンドの用法やカスタムマクロの説明が端的にまとまっている。
GnuPG (The GNU Privacy Guard) !!!
Notes:
GnuPGの基礎知識がまとまっている。
鍵に対する署名
前述の通り、GPGではWeb of Trustの仕組みを利用します。公開鍵への署名は、公開鍵のフィンガープリントを--sign-keyオプションで指定します。その後、その情報を共有するため、公開鍵の鍵IDまたはフィンガープリントを--send-keysオプションで指定して、鍵サーバーに送ります。
公開鍵(自身のを含む)の署名情報を更新するために、--refresh-keysを実行する必要がある。
GPGキーの削除
作成したGPGキーを削除する方法は以下。秘密鍵を削除してから公開鍵を削除する。
秘密鍵:
公開鍵:
生成したGPGキーをエクスポートして、RPMにインポートすることもできる。
RPMレポジトリのGPGキーを除去する方法は以下。
References
rpm --import or gpg --import
利用しているパッケージ管理次第では、両方必要であったり、どちらも使用しなくてもインストールの過程で必要に応じて鍵をインポートするといったこともある。 相互に作用したり、片方しかなければ独立したような動作になることもある。
References
秘密鍵のエクスポート
2.2.33では以下。
2.0.22では以下。
gpg --list-secret-keysを2回繰り返しているのは初回実行時に以下のようにgpgからのメッセージが出てしまうため。
オプション
man gpgの結果でいくつかオプションを記載。使用したオプションをいくつか抜粋。
--sign / --clear-sign / --detach-sign の違い
-s(--sign)
ファイルへの署名
バイナリファイルが生成
--clear-sign
データを残したまま署名
ファイル上部に署名した元データが入っている
--detach-sign
元のデータと署名ファイルを分離して生成
署名の検証をユーザーに強制したくない場合等
適宜、以下のオプションも併用する形で活用すると良い。
-a(--armor)
出力をバイナリではなくASCII(テキスト)形式で出力
Webサイトやメールの本文でデータをやり取りする場合
References
公開鍵の共有方法
手作業で交換する方法
鍵サーバーを使って交換する方法
1つめについて、例えば、公開鍵を手作業で交換したものを以下のようにインポートできる。(公開鍵の例は https://gnupg.org/signature_key.html のものを使用)
2つめについては、以下のようにインポート。
鍵サーバーには種類があるので、好きなものを選べば良い。SKS Keyserver Network(hkp://keys.gnupg.net)がDeprecated。そのため、他のGPG鍵サーバーを利用すると良い。
keyserver.ubuntu.com
keys.openpgp.org
pgp.mit.edu
鍵サーバーがSPOFになる可能性があるが、鍵サーバープールを使用することで、鍵サーバーを集めることによって信頼性が保証される。
GPGの設定ファイル~/.gnupg/gpg.confのkeyserverに指定する。
利用例
たとえば、MySQLではGPGを利用したインストール方法について、以下のように案内されています。
Operator SDKでは、以下のように案内されています。
Topics
GPGに関連するいくつかの話題について触れていきます。
Yumレポジトリの作成
自前でYumレポジトリを作成します。このとき、レポジトリで管理するRPMにGPG鍵で署名しておきます。
最初に、Yumレポジトリを作成する上でオプションの作業ですが、GPG鍵に秘密鍵で署名しておきます。gpg --export -a 'Test1'コマンドで公開鍵をエクスポートしたものは後ほど使用するので、控えておきます。
Webサーバーを用意し、そこにRPMパッケージを配置します。ここでは、Apacheを使用します。作成したディレクトリ直下(/var/www/rpmrepo/x86_64/rpmtest)に目的のrpmファイル(ここでは、motd-1.0-1.amzn2.noarch.rpm)を配置します。
Apacheの設定ファイルを変更します。
設定を読み込みます。
Yumレポジトリを作成していきます。createrepo_cパッケージをインストールします(createrepoはobsoleted)。
実際にレポジトリを作成します。レポジトリ内のファイルを更新した場合は、--updateオプションを付与してコマンドを実行します。アーキテクチャ毎にディレクトリを作成する場合は、それごとにcreaterepoコマンドを実行する。
するとrepodataというディレクトリとその配下にメタデータが作成され、ここにrepomd.xmlも作成されます。treeコマンドでディレクトリを確認すると以下のようになっています(インストールしていない場合は、yum install tree -yでインストール可能)。
repomd.xmlには以下のようなファイルが作成されています。
クライアント側でレポジトリの設定をします。
gpg --export -a 'Test1'で出力したファイルを例えば、RPM-GPG-KEY-pbuild-sample1といったファイル名で作成し、これに貼り付けます。その後、RPMに読み込みます。
キャッシュをクリアします。
レポジトリが追加されていることが確認できます。
レポジトリ情報が確認できるようになります。
以下のようにインストールできるようになります。
GPG鍵でRPMに署名していない場合は、以下のようにインストールが中断して、実行できません。その場合、署名するか、gpgcheck=0オプションを先程のrepoファイルに追加する必要があります。
References
*** カスタムRPMや独自yumリポジトリではじめるソフトウェア管理術
Notes
/etc/yum.repos.dディレクトリ内の設定ファイルと、公開鍵の設定をいちいち手動で実行するのは手間がかかるため、これらを自動で行えるRPMパッケージを配ると便利。
Notes
各種Yumの操作が参考になる。
署名処理の自動化
GPG Agent + Preset phraseの利用(後述)
expectコマンドと
--passphrase-fdオプションを利用してパスワード入力する方法
2つめについて、例えば、以下のコマンドを実行する。
gpg-agent
gpg-agentは GnuPGの中核コンポーネントで,秘密鍵の管理を行い一定期間キャッシュ
gpg、gpgconf、gpg-connect-agentなどのコンポーネントから起動し、互いに通信起
Pinentry
PinentryはパスフレーズやスマートカードのPINコードを入力する際にgpg-agentから呼び出し
gpgに
--batch、--pinentry-mode loopbackオプションとパスフレーズ指定オプション(--passphrase, --passphrase-fd, --passphrase-file)をセットで指定している場合はPinentryを迂回する方法もある。
GnuPG 2.1.0からgpg-agentとpinentryの利用が必須
これによって
--passphrase-fd 0コマンドラインオプションによって STDIN からパイプで渡されたパスフレーズの後方互換性が損ねられています。古いリリースと同じような機能を使うには2つのことをする必要があります:
loopback pinentry モードの許可
``~/.gnupg/gpg-agent.conf
にallow-loopback-pinentry`を追加し、設定ファイルの読み込み。
gpgコマンドをloopbackモードで使用。以下2通りの方法。
gpgコマンドの
--pinentry-mode loopbackオプション~/.gnupg/gpg.confにpinentry-mode loopbackを追加
実際に動作を検証。
~/.gnupg/gpg-agent.confに以下のようなファイルを作成し、適宜設定を事前に読み込んでおく。
以下のように実行。KeygripはOpenPGP鍵以外の鍵にも対応するためのもの。
以下のように実行すると、特にパスワードを要求されることなく、署名ができる。
gpg-agentをssh-agentとして使用
gpg-agentがSSH-agentとしても機能するようにする。
~/.gnupg/gpg-agent.confにenable-ssh-supportを追加。
GPG最新バージョンをインストール
CentOSやUbuntuでレポジトリからGPGをインストールしてきても、最新は2.3.3。LTSで2.2.33(?)だが、2.0.22と古い。
Errors
以下、検証時に遭遇したエラーと対処法のまとめを記録。
rpm: /usr/bin/rpmsign: No such file or directory
以下のコマンドを実行したところエラー
--addsignオプションを使用するためには別途rpm-signライブラリをインストールする必要がある。
You must set "%_gpg_name" in your macro file
以下のコマンドを実行したところエラー
以下のように実行すればOK。
もしくは、.rpmmacrosに%_gpg_nameを定義する形でも良い。
error: rpmMkTemp failed
sudoをつければエラー解消
gpg: packet(3) with unknown version 0
もともとのカスタムマクロは以下だった。
gpgコマンド実行時におけるオプション指定がそもそもだめだった。--signと--detach-signを添えてあげる必要があった。以下で問題を解消した。
上記原因を見つけるために、gpgコマンドで実際の動作確認をしてデバッグしていった。
その後、.rpmmacrosをゼロベースで作成しながら、raw RPM マクロ定義に値が反映されているかを確認しながら検証していった。
上記確認の都度、raw RPM マクロ定義に反映されていっているか確認をしていった。
その後、以下のようにファイル名を変更して、--macros=custom_rpm.macrosオプションを指定して実行できるようにした。
以下を用意し、デバッグをしやすいようにしておいた。
Pass phrase check failed or gpg key expired
rpm --addsignを実行したところ、以下のエラー。
ここでは、GnuPGの設定は不要であったため、一旦すべて削除することで解消
__gpg_signで入力待ち
いずれの場合も必要な情報がrpmコマンドに適切に入力できていないために状況が発生していた。
Pattern 1
以下の状態だと、その外のfor文で読み込んでいたfor rpm_file in cat $fileのcat $fileがファイルディスクリプターのNo.0としてこれを読み込んでいた。
--passphrase-fdを指定しないと、cat $fileをstdinの情報として読み込み、入力待ち状態になってしまっていたことが原因。
そのため、これを実行していたexpect文の末尾に3<&0を追加し、標準入力を新しいファイル記述子に複製して、--passphrase-fd 3のようにファイルディスクリプターの番号を引数として指定した
Pattern 2
expectコマンド中で使用していたが、expect命令で指定していた一致するメッセージが来ないため、待機状態になっていた。
gpg: skipped "Sample1": No secret key
rpmコマンドで--addsignを実行したところ、以下のエラー。spawnはexpectコマンド中で使用しているため。
秘密鍵をインポートしていなかったことが原因。秘密鍵をインポートすれば解消。
error: Macro % has illegal name (%define)
いらない二重引用符をつけていた
warning: motd-1.0-1.amzn2.noarch.rpm: Header V4 RSA/SHA1 Signature, key ID ac73620c: NOKEY
パッケージをダウンロードしてrpmコマンドでインストールする場合、自動でGPG署名のチェックが行われるが、パッケージリリース元のGPG公開鍵がサーバに取り込まれていない場合以下のような警告が出る
正しく署名の確認を行うにはGPG公開鍵のインポートを行わなくてはならないrpm --import /Path/To/PublicKeyのようにインポートする。
References
gpg-agent: no gpg-agent running in this session
--daemonをつけて起動する必要があった。
References
ERR 67108924 Not supported - no --allow-preset-passphrase
gpg-connect-agentコマンドでPRESET_PASSPHRASEでパスワードを事前登録しようとしたところ下記のエラー
~/.gnupg/以下にgpg-agent.confという名前のファイルを作成し、allow-preset-passphraseの文字列を追記した上でGPG Agentの設定を読み込み直す必要があった。
gpg: Can't check signature: Invalid public key algorithm
Amazon Linux 2上だと、以下のエラー
検証環境のバージョンは以下。
バージョンが古いことが原因だった。以下のようにバージョンを上げたところ、解消
MacOS上だと、バージョンが2.2.33であるため、最初から正常に検証できる。
References
gpg: error while loading shared libraries: libgcrypt.so.20: cannot open shared object file: No such file or directory
Amazon Linux 2の環境で、GnuPGの最新版をインストールし、コマンドを実行しようとしたところ、以下のエラー。
以下を実行する必要があった。ライブラリのインストール先をgpg2.confに指定して、ldconfigコマンドで読み込む。
gpg: agent_genkey failed: No pinentry
gpgをインストール後コマンドを実行すると以下のエラー
gpg-agent.confに設定を追加して、gpg-agentの設定を読み込み直す必要があった。
gpg: key AAC5DE59A84FCD28/AAC5DE59A84FCD28: error sending to agent: Operation cancelled
gpg --importしたところ、操作が途中でキャンセルされている。秘密鍵のインポートがOperation cancelledと表示されている。
rpm --importでパスワード入力していないことが原因。パイプライン中ではインタラクティブなパスワード入力画面がないことに起因。ためしに、GPGの鍵生成時にパスワードを設定せずに実行したところ、以下のように正常に実行された。
パスワードが設定された状態でも、--batchオプションで解消した。
rpm: /usr/bin/rpmsign: No such file or directory
rpmコマンドで--addsignオプションを付与して実行したところ、以下のエラー。
rpm-signをインストールして解消。
configure: error: libgpg-error is needed.
Amazon Linux 2で、rootユーザー環境で、libgpg-errorに依存する他のライブラリを./configureするときに、既にインストールされているにも関わらず、上記エラー。ec2-userだと問題なく、インストールできる。
ライブラリの場所を明示的に指定する必要があった。libgpg-error以外の他のライブラリも同様。./configure --helpでそれらしきオプションを探してくる。
You need libksba to build this program.
ntbtlsをビルド時に以下のエラー
--helpオプション上は--with-libksba-prefixとなっているが、--with-ksba-prefixが正しい。libksbaのバグ。
References
No package 'gnutls' found
./configureを実行していたところ、上記エラー。gnutls-develをインストールする。
References
No package 'sqlite3' found
./configureを実行していたところ、上記エラー。sqlite-develをインストールする。
WARNING: server 'gpg-agent' is older than us (2.0.22 < 2.2.33)
gpg-agentのバージョンがgpgよりも古いことが原因。 合わせて他の関連バイナリのバージョン(gpg-agent, gpg-connect-agent, gpgconf)もgpgに合わせた。
gpg --importがexit 2で終了する。
バージョンによって挙動が異なることもある様子。自己署名のようなログが流れていたのでそれに起因している可能性がある。
スクリプトを終了するような環境で処理を止めたくない場合は || trueのように実行することもできるが、GPG鍵をインポートしたくてもバージョンが古く対応していないアルゴリズムで署名されていたので、回避策として、ファイルのハッシュ値を比較して、GPG鍵を利用しない方向で対応した。
gpg: pinentry launched (23774 unknown 0.8.1 ? ? ?)
rpm --addsign実行時に、以下のメッセージが出て処理に失敗。
expectコマンド中での場合は、以下のようなエラー。
以下のようなパスワード入力画面が出てしまっていることが理由。
インポートしている秘密鍵と実際に指定しているGPG名が不一致で、GPGエージェントによるパスワード入力が効かなかったことが原因。以下のようにechoによるパスフレーズ(echo "PRESET_PASSPHRASE $GPG_KEYGRIP -1 $GPG_PASSPHRASE_HEX" | /usr/local/bin/gpg-connect-agent -S $GPG_AGENT_SOCKET)を実行していた。
以下がechoコマンドによるもののときのログ
/usr/libexec/gpg-preset-passphrase --passphrase $GPG_PASS_PHRASE --preset $GPG_KEYGRIPを実行の方がシンプルで、こちらを利用することにした。
References
gpg: keyserver receive failed: No name
Ubuntu上で実行したところ以下のエラー
SKS Keyserver NetworkがDeprecatedになって、利用できない状態。そのため、他のGPG鍵サーバーを利用すると良い。
keyserver.ubuntu.com
keys.openpgp.org
pgp.mit.edu
References
gpg: Can't check signature: No public key
Amazon Linux 2上で以下のようにキーをインポート後、
以下のように署名を検証
すると以下のエラー
SKS Keyserver NetworkがDeprecatedになって、利用できない状態。そのため、他のGPG鍵サーバーを利用すると良い。
References
Links
GnuPG
Practice
Notes
入門記事
Notes
リファレンスとして良い
GPG でファイルを暗号化, 復号化, 署名, 検証する方法 !!
Notes
gpgコマンドによる暗号化、復号、署名、検証方法の代表的なパターンが一通り書かれている。
GPG でファイルをパスワードで暗号化(共通鍵暗号)するときの簡易コマンド一覧
Notes
gpgの利用例
Notes
以下のパターンでの使い方を解説
「電子署名が付加」されただけのPGP MESSAGE
「ファイルを暗号化」しただけのPGP MESSAGE
「電子署名 + 暗号化」がファイルに施されたPGP MESSAGE
Notes
パッケージの署名には、以下の 3 つの方法があります。
「既存パッケージへの署名の追加」.
「既存のパッケージの署名の置き換え」.
「ビルド時のパッケージの署名」.
RPM
Overview
Last updated