Bitcoinいれるならgpg を理解せよ

Masashi Nakane
暗号通貨 とセキュリティ
23 min readMay 10, 2018

ソフトウエアをインストールする際に、とても重要になるのは? それは、ハッカーが改造したバージョンを意図せずにインストールしないことである。他のホワイトハックの記事を見たらわかるように、世界にはハッキングの方法は山ほどあるし、これからもまだまだ新しいアタック方法が出てくる。

BitcoindやLightningdなどをインストールし、自分の大切な資産(ビットコインなど)を、使う時に、ハッカーのアドレスに送金するように仕組まれたソフト、秘密鍵をハッカーへ送付するようなロジックの仕込まれたソフトをインストールしてしまっては絶対にいけない。(どんなハッキングプログラムでも、それをインストールしてしまったらコンピューターもしくはOSは、ハッカーの思い通りになってしまうのでBitcoinソフトに限った話ではない。)

Linuxでソフトを使う場合に、理解しておきたいのが、GPG(Gnu Private Guard)と呼ばれるLinuxで標準の公開鍵を使ったソフトウエアの検証の仕組みである。どう使うかというと、自分が意図した作成者が作ったソフトであるか、作成者の公開鍵を使い、使うインストーラーが本物である事を検証(ハッキングロジックが仕込まれてない可能性が非常に高いと確認)してからインストールするのだ。

ソフトウエアの検証では、ソフトウエアのソースかバイナリーとシグニチャを、作者の公開鍵を使って検証するだけだが、もうすこし踏み込んで理解するために。自分でもGPGを使って鍵を作り、公開し、暗号化と検証としてサインをしてみよう。これは公開鍵システムの基本の理解にもつながるので、ぜひ試してもらいたい。

細かい詳細については、このDocumentを参照してほしい。(以降、Ubuntu 16.04 LTSの例)

鍵の作成

キーペア(秘密鍵と公開鍵)を作成するコマンドは、以下だ。

gpg --gen-key

実行結果は、以下のようになる。.gnupgというフォルダが作成されその中に、2つのキーリング(鍵束、デジタル鍵のデータを複数保管するファイル)が作成されている。

masa@masa-Vostro-3800:~$ gpg --gen-key
gpg (GnuPG) 1.4.20; Copyright (C) 2015 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: directory `/home/masa/.gnupg' created
gpg: new configuration file `/home/masa/.gnupg/gpg.conf' created
gpg: WARNING: options in `/home/masa/.gnupg/gpg.conf' are not yet active during this run
gpg: keyring `/home/masa/.gnupg/secring.gpg' created
gpg: keyring `/home/masa/.gnupg/pubring.gpg' created

暗号の種類とRSAキーの長さは、デフォルトのRSAを使い、鍵の寿命を1年にしてみよう。

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)
Your selection?
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (2048)
Requested keysize is 2048 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) 1y
Key expires at Wed 01 May 2019 06:38:00 AM PDT
Is this correct? (y/N) y

次は、名前とメールアドレスとコメント(ニックネームとか)だ。ここでは、架空のテスト用のメールアドレスを使用した。

You need a user ID to identify your key; the software constructs the user ID
from the Real Name, Comment and Email Address in this form:
“Heinrich Heine (Der Dichter) <heinrichh@duesseldorf.de>”
Real name: test name
Email address: test@test.com
Comment: test test
You selected this USER-ID:
“test name (test test) <test@test.com>”
Change (N)ame, ©omment, (E)mail or (O)kay/(Q)uit?

そして、とても大事な秘密鍵を守るためのパスフレーズを2回入力する。ディクショナリーアタックや、ブルートフォースに強く、かつ忘れないフレーズを設定しよう。(文字と記号と数字が入った長めのもの、しかも忘れないもの)すると、OSのエントロピーを利用して、ランダムな鍵(秘密鍵と公開鍵)を生成する。

しかし、十分なエントロピーを得られない場合。危険(鍵が十分にランダムにならないので衝突や、同じ鍵が生成されやすい)なので、エラーが出ることがある。

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.
Not enough random bytes available. Please do some other work to give
the OS a chance to collect more entropy! (Need 41 more bytes)

その場合、以下のように乱数生成ツールをインストールし、ランダムな数字を外部環境から取得しOSに渡してもらう。それから、もう一度gpg -gen-keyコマンドを実行してみよう。

sudo apt-get install rng-tools
sudo rngd -r /dev/urandom
gpg -gen-key

すると、鍵が無事作成され、キーリングに、書き込まれる。公開鍵の鍵IDは,13EB7614だった。同時に、自分の秘密鍵を使って、自分の公開鍵に、サインもしているのが見える。これは、”この公開鍵とその持ち主は信用できる”と、宣言していることになる(自分のことなので当然だが)。

だれか信頼できる人の公開鍵を手に入れたとしょう、例え、その人のメールアドレスなどが、ユーザーIDになっていても、本当に本人のものと完全に確証するためには、公開鍵のフィンガープリントを、(理想的には、その信頼できる)本人から直接聞き公開鍵がその人のものであるか確実に確認する必要がある。(フィンガープリントとは、公開鍵の一部をハッシュ値で計算したものでそれがあっていれば確実に公開鍵はその人のものだ。ハッシュ計算の詳細はこちら

……..+++++
.+++++
gpg: key 13EB7614 marked as ultimately trusted
public and secret key created and signed.
gpg: checking the trustdb
gpg: 3 marginal(s) needed, 1 complete(s) needed, PGP trust model
gpg: depth: 0 valid: 2 signed: 0 trust: 0-, 0q, 0n, 0m, 0f, 2u
gpg: next trustdb check due at 2019–05–01
pub 2048R/13EB7614 2018–05–01
Key fingerprint = B92E 5670 E0BE D1CB 3624 F01F BFD7 C617 73EC E6C2
uid test name (test test) <test@test.com>
sub 2048R/FA42176D 2018–05–01

では、キーリングの中を見てみよう。公開鍵の一覧はこうだ。

masa@masa-Vostro-3800:~$ gpg --list-keys
/home/masa/.gnupg/pubring.gpg
— — — — — — — — — — — — — — -
pub 2048R/4DD7ECA5 2018–05–01 [expires: 2019–05–01]
uid Masashi Nakane (hypergori) <masashi.nakane@gmail.com>
sub 2048R/9AEF9B6B 2018–05–01 [expires: 2019–05–01]
pub 2048R/13EB7614 2018–05–01 [expires: 2019–05–01]
uid test name (test test) <test@test.com>
sub 2048R/7F9CCE26 2018–05–01 [expires: 2019–05–01]

鍵はどこにあるかというと、ホームディレクトリの.gnupgフォルダだ。pubring.gpgが公開鍵の鍵束で、secring.gpgが秘密鍵の鍵束、trustdb.gpgが公開鍵のサインが入ったデータベースとなる。

masa@masa-Vostro-3800:~$ ls -l .gnupg
total 36
-rw — — — — 1 masa masa 9398 May 1 07:43 gpg.conf
-rw — — — — 1 masa masa 2432 May 1 07:47 pubring.gpg
-rw — — — — 1 masa masa 2432 May 1 07:47 pubring.gpg~
-rw — — — — 1 masa masa 600 May 1 07:47 random_seed
-rw — — — — 1 masa masa 5128 May 1 07:47 secring.gpg
-rw — — — — 1 masa masa 1360 May 1 07:47 trustdb.gpg

鍵のインポート/エクスポート

コンピューターで作成した鍵は、バックアップしたり、コンピューター間の移動をするためにエクスポートとインポートが可能だ。

gpg --export > all.gpggpg --import all.gpg

キーサーバーから公開鍵の取得

ここまでは、鍵の作成についてやってみた。次に、自分の公開鍵を世界に公開するために、キーサーバーへの送信をやってみる。が、その前に、公開されている公開鍵がどう見えるかbitcoin coreをインストールする際に使うインストーラーレポジトリ用(Launchpad ppa)のものを見てみよう。

まずは、キーサーバーのWEBサイトで検索してみる。検索キーワードは、”Launchpad PPA for Bitcoin”だ。

無事に、見つかったので、次はコマンドラインで、キーサーバーから公開鍵を8桁の鍵IDをつかって取得してみる。

masa:~$ gpg --keyserver keyserver.ubuntu.com --recv-keys 8842CE5E
gpg: requesting key 8842CE5E from hkp server keyserver.ubuntu.com
gpg: key 8842CE5E: public key “Launchpad PPA for Bitcoin” imported
gpg: 3 marginal(s) needed, 1 complete(s) needed, PGP trust model
gpg: depth: 0 valid: 2 signed: 0 trust: 0-, 0q, 0n, 0m, 0f, 2u
gpg: next trustdb check due at 2019–05–01
gpg: Total number processed: 1
gpg: imported: 1 (RSA: 1)

ここで、gpg公開鍵の一覧を再度、見てみると、bitcoinインストーラーの公開鍵が追加されていると分かる。

masa@masa-Vostro-3800:~$ gpg --list-keys
/home/masa/.gnupg/pubring.gpg
— — — — — — — — — — — — — — -
pub 2048R/4DD7ECA5 2018–05–01 [expires: 2019–05–01]
uid Masashi Nakane (hypergori) <masashi.nakane@gmail.com
sub 2048R/9AEF9B6B 2018–05–01 [expires: 2019–05–01]
pub 2048R/13EB7614 2018–05–01 [expires: 2019–05–01]
uid test name (test test) <test@test.com>
sub 2048R/7F9CCE26 2018–05–01 [expires: 2019–05–01]
pub 1024R/8842CE5E 2011–10–26
uid Launchpad PPA for Bitcoin

キーサーバーから公開鍵の公開

では、今度は、自分の公開鍵を、アップロードしてみよう。

masa:~$ gpg --keyserver keyserver.ubuntu.com --send-key 13EB7614
gpg: sending key 13EB7614 to hkp server keyserver.ubuntu.com

そして、キーサ―バーのWebで調べると、キーサーバーで自分の公開鍵が公開されているのがわかる。

鍵の取消証明

このタイミングでやってみたいのが、鍵の取り消し証明書の作成である。取り消したくなる理由はいくつかある。

  1. 秘密鍵が盗まれた。(ハッカーが侵入して取られた)
  2. 秘密鍵をなくした。(コンピューターを盗まれた、失くした、壊れた)
  3. メールアドレスや名前が変わった。
  4. 鍵のサイズを大きくしたい。

などだ。なぜ今かというと、パスフレーズを忘れてしまうかもしれないからだ。すなわち、取消の目的には、もう1つある。結構、ありそうなケースだ。

5. 秘密鍵の開くパスフレーズを忘れた。(サインも、検証もできない。)

この取消パターンを考慮にいれると、取消証明書の作成は、今しかない。以下のように取消証明書を作成し、大事に保管し、その時がきたら、取り消して新しい鍵をつくることになる。

masa@masa-Vostro-3800:~$ gpg --gen-revoke “test@test.comsec 2048R/13EB7614 2018–05–01 test name (test test) <test@test.com>Create a revocation certificate for this key? (y/N) y
Please select the reason for the revocation:
0 = No reason specified
1 = Key has been compromised
2 = Key is superseded
3 = Key is no longer used
Q = Cancel
(Probably you want to select 1 here)
Your decision? 1
Enter an optional description; end it with an empty line:
> my PC is stolen with my privatekey. So thie public key is not valid any longer .
>
Reason for revocation: Key has been compromised
my PC is stolen with my privatekey. So thie public key is not valid any longer.
Is this okay? (y/N) y
NOTE: This key is not protected!
ASCII armored output forced.
Revocation certificate created.
Please move it to a medium which you can hide away; if Mallory gets
access to this certificate he can use it to make your key unusable.
It is smart to print this certificate and store it away, just in case
your media become unreadable. But have some caution: The print system of
your machine might store the data and make it available to others!
— — -BEGIN PGP PUBLIC KEY BLOCK — — -
Version: GnuPG v1
Comment: A revocation certificate should follow
iQFuBCABAgBYBQJa6dMFUR0CbXkgUEMgaXMgc3RvbGVuIHdpdGggbXkgcHJpdmF0
ZWtleS4gU28gdGhpZSBwdWJsaWMga2V5IGlzIG5vdCB2YWxpZCBhbnkgbG9uZ2Vy
LgAKCRCbT93SE+t2FLfJB/0YvwK7FeY9RENrnTlwC0jAHNc62ULf1A+ADiyBKRqg
G8QxpnqV3Bu+nDu21IolYFvBQVW3GFS/bHWE+yQDVoXCwY0ij5rP9Y2vRV/KcBJ4
WKXYPc2anJeEtmjEw4qZbC2Vs/xT/rJ7hSp1gi/EFchxYugWN9iVsZ0VxJi0Ldhs
07q86btmirUAZtW41GvMTxvmgcBgPb7gF3lnpADkdo+UjSaPsNP2PbvxbZOWrws0
1OxQjptazvW2jsjhX0OUyXpkgRFRLnc3uh0Va+af7WXl6TlT6bF2NL1xPDh+Q9KB
CeHBPBFw52RbCL07jdqMfPKXsFuprvwc6gVjDC0bhs5p
=mhTe
— — -END PGP PUBLIC KEY BLOCK — — -

GPGドキュメントには、紙に印字して、オフラインに、すなわち金庫などにしまっておく、などとある。(取り消すときは、OCRスキャナーでファイルに取り込んで、処理するのだろうか。)

作成した取消証明書で、鍵を取消す場合には、まずローカル(自分のコンピューター)で、取消証明のテキストファイルを作成し、該当の公開鍵を取消し、それからキーサーバーに公開する。

#エディターでファイルに--PGP PUBLIC KEY BLOCK--のブロックを書いて保存する。
nano revocation.cert

nano エディーターを開いて、下のように取消証明のブロック部分をコピーし、Ctrl-xで終了すると保存ファイル名を聞かれるので適当な名前で保存する。

そのあと、取消証明ファイルをインポートしてからキーサーバーに送信すれば先ほどの公開鍵が取消状態になり、だれも使わなくなる。

gpg --import revocation.cert
gpg --keyserver keyserver.ubuntu.com --send <your key id>

どうなったか、キーサーバーのWEB画面で検索してみよう。

公開鍵で暗号化

テキストファイルやバイナリーファイルを、送り先の公開鍵で暗号化することで、送信途中での盗み見や改ざんを防ぐことができる。相手方は自分の秘密鍵で復号するからだ。ハッカーが盗みみようとしても秘密鍵がないので、みれないし、暗号化されたファイルを改ざんしても、復号できなくなる。しかし、誰でも送付先の人の公開鍵は取得できるので、送信元の身元を証明するためにシグニチャを付けるほうがよい。相手が安心して、あなたが送信元であると検証(あなたの公開鍵を使って)することができるからだ。

まずは、自分の公開鍵を使って暗号化してみよう。sample.txtは適当につくったテキストファイルだ。

gpg --recipient masashi.nakane@gmail.com --encrypt sample.txt

すると,sample.txt.gpgというファイルができる。復号化してみよう。秘密鍵を使用するためパスフレーズを聞かれる。あなたがパスフレーズを覚えていることを祈る 😆

masa@masa-Vostro-3800:~$ gpg --decrypt sample.txt.gpgYou need a passphrase to unlock the secret key for
user: “Masashi Nakane (hypergori) <masashi.nakane@gmail.com>”
2048-bit RSA key, ID 9AEF9B6B, created 2018–05–01 (main key ID 4DD7ECA5)
gpg: gpg-agent is not available in this session
gpg: encrypted with 2048-bit RSA key, ID 9AEF9B6B, created 2018–05–01
“Masashi Nakane (hypergori) <masashi.nakane@gmail.com>”
Hello World GPG

デフォルトでは、標準出力に復号結果がでてくるので、一番下に、”Hello World GPG”と見えるだろう。

サインと検証

では、送信元として確認してもらうために、秘密鍵を使ってシグニチャを作成し、相手先には、私の公開鍵で検証してもらう。

おなじテキストデータを使用する。

masa@masa-Vostro-3800:~$ gpg --sign sample.txtYou need a passphrase to unlock the secret key for
user: "Masashi Nakane (hypergori) <masashi.nakane@gmail.com>"
2048-bit RSA key, ID 4DD7ECA5, created 2018-05-01

sample.txt.gpg というテキストデータと署名が1つになったファイルができている。エディターでみて、気付いてほしいのは、データは、暗号化せず、署名をくっつけているファイルになっていることだ。もうちょと見やすい署名の仕方は、こう。

 gpg — clearsign sample.txt

これは、テキスト形式の署名を作成してもとのファイルにつけるので見やすい。こう見える。sample.txt.ascというファイルのがあるので開く。

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Hello World GPG
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1
iQEcBAEBAgAGBQJa9FFiAAoJEDPywtZN1+yld08H/jXxBCLzu15Rr8ofWiCKIImD
ZN2uYw99AjgvB63GfQk5Rp9/Gq5gw3F84qeHsLCM/YTBGrE2d/My4pEHuoCckZf3
Z93rX9wWdIAsv1gEb0z7IF6dOdj6necgBaB72OBblnoNEiOl+0YmS9D6CoqOcbmK
1FJQgC4TRV/WqcxnRNSGVk03jdfLiZOE4L5MtnyT9oDq4WMoCFA2G9DoNXMr9Kys
ERN7NdxG1fG65uGoOu2//iT7kqT2TH02IznCqhlBwNtmQ4oxoHo4Aek/05BfaTZF
9waoe9uitKh1MnXPgA0cx+Sop8ctWMX72nnmzesEIqwKKGJOqF2HqyRo2pTvwBk=
=Ile+
-----END PGP SIGNATURE-----

では、デッカイファイル。例えば、バイナリーのインストーラーの署名はどうするだろうか。本体と署名が1つだとデカすぎるので、署名だけ抜き出したファイルにする。

gpg --detach-sign sample.txt

こんどは、sample.txt.sigというファイルができる。

同様に、テキスト形式の署名のみのファイルを作る場合は、

gpg --armor --detach-sign sample.txt

最終形として、送り先の公開鍵で暗号化しつつ署名をつけたファイル(暗号化されたデータ+署名)の作り方はこうなる。あまり、実質的な意味はないが、自分をあて先に、して自分の秘密鍵で署名をする。

gpg -user masashi.nakane@gmail.com --recipient masashi.nakane@gmail.com --armor --sign --encrypt sample.txt

最後に、検証してみよう。

masa@masa-Vostro-3800:~$ gpg --verify sample.txt.sig
gpg: assuming signed data in `sample.txt'
gpg: Signature made Thu 10 May 2018 07:14:01 AM PDT using RSA key ID 4DD7ECA5
gpg: Good signature from "Masashi Nakane (hypergori) <masashi.nakane@gmail.com>"

“Good signature”とあり検証が成功した。

ここまで自分の手でやってみると、pgpを使った公開鍵と秘密鍵、署名と検証の感覚がつかめたと思う。bitcoin等のlinuxソフトウエアのインストール時には、gpgを使ったインストーラーの検証を必ず意識し、Dockerファイルやshellのインストールコマンドに、gpgでの検証が入っているか確認しよう。

--

--