GnuPG による暗号化

June 10, 2018

ファイルを暗号化したい場合、Linux では GunPG (GNU Privacy Guard) が利用できる。GnuPG は公開鍵暗号を使って、ファイルを暗号化/複合したり、電子署名したりすることのできるソフトウェア。

鍵ペアの作成と失効証明書の作成

GnuPG (GPG) を使用するためには gpg コマンドを使用する。最初に以下のように公開鍵の鍵ペアを作成する必要がある。

$ gpg --gen-key  
gpg (GnuPG) 2.0.28; 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/ec2-user/.gnupg' created  
gpg: new configuration file `/home/ec2-user/.gnupg/gpg.conf' created  
gpg: WARNING: options in `/home/ec2-user/.gnupg/gpg.conf' are not yet active during this run  
gpg: keyring `/home/ec2-user/.gnupg/secring.gpg' created  
gpg: keyring `/home/ec2-user/.gnupg/pubring.gpg' created  
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) 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 Mon 10 Jun 2019 05:04:53 PM JST  
Is this correct? (y/N) y  
  
GnuPG needs to construct a user ID to identify your key.  
  
Real name: Hoge Hoge  
Email address: hoge@example.com  
Comment:   
You selected this USER-ID:  
    "Hoge Hoge <hoge@example.com>"  
  
Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? o  
You need a Passphrase to protect your secret key.  
  
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.  
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.  
gpg: /home/ec2-user/.gnupg/trustdb.gpg: trustdb created  
gpg: key FA512E6B 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:   1  signed:   0  trust: 0-, 0q, 0n, 0m, 0f, 1u  
gpg: next trustdb check due at 2019-06-10  
pub   2048R/FA512E6B 2018-06-10 [expires: 2019-06-10]  
      Key fingerprint = 2071 0720 B0F7 5061 94D4  9F6C 420C 4BA7 FA51 2E6B  
uid       [ultimate] Hoge Hoge <hoge@example.com>  
sub   2048R/92B302FC 2018-06-10 [expires: 2019-06-10]  

~/.gnupg というディレクトリが新たに作成され、その中に公開鍵のキーリング (pubring.gpg) と秘密鍵のキーリング (secring.gpg) が作成される。

$ gpg --list-keys  
/home/hoge/.gnupg/pubring.gpg  
---------------------------------  
pub   2048R/FA512E6B 2018-06-10 [expires: 2019-06-10]  
uid       [ultimate] Hoge Hoge <hoge@example.com>  
sub   2048R/92B302FC 2018-06-10 [expires: 2019-06-10]  

鍵の失効証明書を作成する必要もある。失効証明書はパスフレーズが漏れたり、パスフレーズを忘れた場合に鍵を無効化するために用いる。

$ gpg -o revoke.asc --gen-revoke hoge@example.com  
  
sec  2048R/FA512E6B 2018-06-10 Hoge Hoge <hoge@example.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:  
>   
Reason for revocation: Key has been compromised  
(No description given)  
Is this okay? (y/N) y  
  
You need a passphrase to unlock the secret key for  
user: "Hoge Hoge <hoge@example.com>"  
2048-bit RSA key, ID FA512E6B, created 2018-06-10  
  
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!  

共通鍵を使ったファイルの暗号化

gpg コマンドを使った最も簡単なのは、共通鍵を使った暗号化となる。
パスフレーズを 2 回入力すると暗号化されたファイルが作成される。

$ gpg -c secret.txt  
$ ls -l secret.txt.gpg   
-rw-rw-r-- 1 ec2-user ec2-user 67 Jun 10 17:14 secret.txt.gpg  

複合するにはオプション無しで gpg コマンドを実行する。

$ gpg secret.txt.gpg   
gpg: CAST5 encrypted data  
gpg: encrypted with 1 passphrase  
File `secret.txt' exists. Overwrite? (y/N) y  
gpg: WARNING: message was not integrity protected  

公開鍵を使ったファイルの暗号化

公開鍵のエクスポート

まず暗号化されたデータを受け取る側は、通信相手に公開鍵を送るため、公開鍵をファイルにエクスポートする。
これで公開鍵が pubkey ファイルにエクスポートされるので、このファイルを通信相手に送る。

$ gpg -o pubkey -a --export hoge@example.com  
$ ls -l pubkey   
-rw-rw-r-- 1 ec2-user ec2-user 1714 Jun 10 17:17 pubkey  

公開鍵のインポート

通信相手から公開鍵を受け取ったら、まずはインポートする。

$ gpg --import pubkey   
gpg: key FA512E6B: public key "Hoge Hoge <hoge@example.com>" imported  
gpg: Total number processed: 1  
gpg:               imported: 1  (RSA: 1)  

インポートされている公開鍵の一覧は次のコマンドで確認可能。

$ gpg --list-keys  
/home/ec2-user/.gnupg/pubring.gpg  
---------------------------------  
pub   2048R/FA512E6B 2018-06-10 [expires: 2019-06-10]  
uid       [ unknown] Hoge Hoge <hoge@example.com>  
sub   2048R/92B302FC 2018-06-10 [expires: 2019-06-10]  

受け取った公開鍵が信頼できるのであれば、鍵に署名を行う。署名を行わなければ公開鍵が信用できないということで、毎回警告が表示される。

$ gpg --sign-key hoge@example.com  
  
pub  2048R/FA512E6B  created: 2018-06-10  expires: 2019-06-10  usage: SC    
                     trust: unknown       validity: unknown  
sub  2048R/92B302FC  created: 2018-06-10  expires: 2019-06-10  usage: E     
[ unknown] (1). Hoge Hoge <hoge@example.com>  
  
  
pub  2048R/FA512E6B  created: 2018-06-10  expires: 2019-06-10  usage: SC    
                     trust: unknown       validity: unknown  
 Primary key fingerprint: 2071 0720 B0F7 5061 94D4  9F6C 420C 4BA7 FA51 2E6B  
  
     Hoge Hoge <hoge@example.com>  
  
This key is due to expire on 2019-06-10.  
Are you sure that you want to sign this key with your  
key "foo <foo@example.com>" (AFD88AB5)  
  
Really sign? (y/N) y  
  
You need a passphrase to unlock the secret key for  
user: "foo <foo@example.com>"  
2048-bit RSA key, ID AFD88AB5, created 2018-06-10  

ファイルの暗号化

受け取った公開鍵を使って、秘密鍵の持ち主 (hoge) だけが複合できるようにする。
これにより important.txt.asc が作成される。

$ gpg -e -a -r hoge@example.com important.txt   
gpg: checking the trustdb  
gpg: 3 marginal(s) needed, 1 complete(s) needed, PGP trust model  
gpg: depth: 0  valid:   1  signed:   1  trust: 0-, 0q, 0n, 0m, 0f, 1u  
gpg: depth: 1  valid:   1  signed:   0  trust: 1-, 0q, 0n, 0m, 0f, 0u  
gpg: next trustdb check due at 2019-06-10  
$ ls -l important.txt.asc   
-rw-r--r-- 1 ec2-user docker 579 Jun 10 08:25 important.txt.asc  

ちなみに普通にファイルを読み込むと、以下のように暗号化されていることがわかる。

$ cat important.txt.asc   
-----BEGIN PGP MESSAGE-----  
Version: GnuPG v2  
  
hQEMA+u+HMOSswL8AQf/UtJvnBwsVVF7Eu1PvdNKZGAVAfrAsxivlk2SQo2z16vs  
tF9ahgN3fMKrOkH+1ctLCrBnVks8Xkl0ijsBRD70tWs/sfusW+BatRl35C/K2Nbd  
3S9jsMsY3hDVNfd8mujHgQJRgmmJ0m+Z482LO3+B/mH298RsCsUK5i3jmqvNkVbP  
jD0OZYTlWo8XymViyLQ3DaYVQijW2MYHyFfPor4ScarxfYwSE2dmRYmpuL+cPSyh  
L8PUp78gKRJTKMIck0knUx6hX+DbiJZoUVg11l7kbZKqzdv/PA8hooToISxv0DZh  
Wumeg9j2r47SqmEtCFQGNZicU7bX1r8tY2vXYIGlW9JeAVkTaCper8CCmwaUPNWH  
FbZ27P4bFQfpm+bOfuwQv6dQUS79WKlVf+Raami1FCD7HgOcrb3JRGpP0kyjYAxC  
fAno+H7g7Chqn0MuIEiKjgPX8zK+8zlU97vbXuM/cw==  
=vPgc  
-----END PGP MESSAGE-----  

ファイルの複合

送られてきたファイル important.txt.asc は秘密鍵により複合可能。

$ gpg important.txt.asc   
  
You need a passphrase to unlock the secret key for  
user: "Hoge Hoge <hoge@example.com>"  
2048-bit RSA key, ID 92B302FC, created 2018-06-10 (main key ID FA512E6B)  
  
gpg: encrypted with 2048-bit RSA key, ID 92B302FC, created 2018-06-10  
      "Hoge Hoge <hoge@example.com>"  
$ cat important.txt  
This is a very important file!  

 © 2023, Dealing with Ambiguity