GPG: 鍵の作成とエクスポート/インポート

鍵署名用の鍵を作る

gpg --full-generate-key --expert コマンドを用いて鍵署名用の主鍵を作成する。ここで作る鍵は副鍵を作るための用途のみであり、単体で利用することはできない。

鍵のアルゴリズムは任意だが、鍵署名専用の鍵を作るためには set your own capabilities のオプションが付いた種類を選んで allowed actions: Certify にする。(Certify 以外を外す)

$ gpg --full-generate-key --expert
gpg (GnuPG) 2.2.27; Copyright (C) 2021 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.

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)
   (7) DSA (set your own capabilities)
   (8) RSA (set your own capabilities)
   (9) ECC and ECC
  (10) ECC (sign only)
  (11) ECC (set your own capabilities)   # <- Select this in example
  (13) Existing key
  (14) Existing key from card
Your selection? 11

Possible actions for a ECDSA/EdDSA key: Sign Certify Authenticate
Current allowed actions: Sign Certify

   (S) Toggle the sign capability
   (A) Toggle the authenticate capability
   (Q) Finished

Your selection? S                        # <- Remove sign

Possible actions for a ECDSA/EdDSA key: Sign Certify Authenticate
Current allowed actions: Certify

   (S) Toggle the sign capability
   (A) Toggle the authenticate capability
   (Q) Finished

Your selection? Q
Please select which elliptic curve you want:
   (1) Curve 25519                       # <-
   (3) NIST P-256
   (4) NIST P-384
   (5) NIST P-521
   (6) Brainpool P-256
   (7) Brainpool P-384
   (8) Brainpool P-512
   (9) secp256k1
Your selection? 1
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) 0
Key does not expire at all
Is this correct? (y/N) y

GnuPG needs to construct a user ID to identify your key.

Real name:
Email address: foo@example.net
Comment:
You selected this USER-ID:
    "foo@example.net"
    
Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? O
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: key 1111111111111111 marked as ultimately trusted
gpg: revocation certificate stored as '/home/user/.gnupg/openpgp-revocs.d/FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF.rev'
public and secret key created and signed.

pub   ed25519 2024-04-01 [C]
      FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
uid                      foo@example.com

$ gpg --keyid-format LONG -K
/home/user/.gnupg/pubring.kbx
-------------------------------
sec   ed25519/1111111111111111 2024-04-01 [C]
      FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
uid                 [ultimate] foo@example.com

$ gpg --keyid-format LONG -k
/home/user/.gnupg/pubring.kbx
-------------------------------
pub   ed25519/1111111111111111 2024-04-01 [C]
      FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
uid                 [ultimate] foo@example.com

副鍵を追加する

上記で作成した鍵は単体で利用することはできないものなので、副鍵を追加する。副鍵は用途ごとに複数追加できる。

鍵の使用法 (usage) について

鍵には使用法を設定する。主鍵作成時には Certify を選択したが、それ以外に Sign, Authenticate, Encrypt の使用法が存在する。鍵に設定されている使用法は gpg -k コマンドなどを使って表示される [C], [S], [A], [E] などの表記で確認することができる。

実際に鍵を追加する

副鍵を追加するには、 gpg --expert --edit-key *KEY-ID* コマンドで操作する鍵を選択してから addkey を指示する。副鍵を作成した後には save の指示をすること (save しないと反映されない)。

データ署名用の副鍵を追加する例:

$ gpg --expert --edit-key 1111111111111111 
gpg (GnuPG) 2.2.27; Copyright (C) 2021 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.

Secret key is available.

sec  ed25519/1111111111111111 
     created: 2024-04-01  expires: never       usage: C
     trust: ultimate      validity: ultimate
[ultimate] (1). foo@example.com

gpg> addkey
Please select what kind of key you want:
   (3) DSA (sign only)
   (4) RSA (sign only)
   (5) Elgamal (encrypt only)
   (6) RSA (encrypt only)
   (7) DSA (set your own capabilities)
   (8) RSA (set your own capabilities)
  (10) ECC (sign only)                   # <- Select this in example
  (11) ECC (set your own capabilities)
  (12) ECC (encrypt only)
  (13) Existing key
  (14) Existing key from card
Your selection? 10
Please select which elliptic curve you want:
   (1) Curve 25519
   (3) NIST P-256
   (4) NIST P-384
   (5) NIST P-521
   (6) Brainpool P-256
   (7) Brainpool P-384
   (8) Brainpool P-512
   (9) secp256k1
Your selection? 1
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) 0
Key does not expire at all
Is this correct? (y/N) y
Really create? (y/N) y
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.

sec  ed25519/1111111111111111 
     created: 2024-04-01  expires: never       usage: C
     trust: ultimate      validity: ultimate
ssb  ed25519/2222222222222222
     created: 2024-04-01  expires: never       usage: S
[ultimate] (1). foo@example.com

gpg> save

主鍵をエクスポートし、端末上から削除する

主鍵は別の鍵を発行する能力を持つので、十分に安全で漏洩が起こりえない場所に保管するべきである。コンピュータの中に保管するのは避け、 (USBメモリなどの) リムーバブルメディアに保存し、物理的なトラブル (盗難、破損など) が起きない場所に保管することを推奨する。

端末に保存されたキーは ~/.gnupg/private-keys-v1.d/ に保存されている。 gpg --with-keygrip -k コマンドを使うことで、どの鍵がどのファイルに保存されているか知ることができる。

$ ls ~/.gnupg/private-keys-v1.d/
4658BD2EB68C52A3A5FAA5A306251E2A6869FB3F.key  E590B6845A28CD09D055F1AAA06D478EF08732FF.key
7FFFCE2F16118B000C9D268402A7CB2FFA6DF53D.key

$ gpg --with-keygrip -k
/home/user/.gnupg/pubring.kbx
-------------------------------
pub   ed25519 2024-04-01 [C]
      FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
      Keygrip = E590B6845A28CD09D055F1AAA06D478EF08732FF
uid           [ultimate] foo@example.com
sub   ed25519 2024-04-01 [S]
      Keygrip = 4658BD2EB68C52A3A5FAA5A306251E2A6869FB3F
sub   ed25519 2024-04-01 [S]
      Keygrip = 7FFFCE2F16118B000C9D268402A7CB2FFA6DF53D

ファイルを直接削除しても目的は達成されるが、コマンドを使って副鍵のエクスポートを併せて行っておくと、後で使いまわせる (別端末で副鍵をインポートするときに使う)

以下の手順を踏む。なお、--armor --output *FILENAME* オプションを指定するとやや取り扱いやすくなる。

  1. gpg --export-secret-keys *KEY_ID* コマンドで、対象の鍵をすべて (主副) エクスポートする
  2. gpg --export-secret-subkeys *KEY_ID* コマンドで、対象の鍵の副鍵をエクスポートする
  3. gpg --delete-secret-key *KEY_ID* コマンドで、対象の秘密鍵 (すべて) を削除する
  4. gpg --import *KEYFILE* コマンドで、副鍵をインポートする
  5. gpg --edit-key *KEY_ID* コマンドで、インポートした副鍵を信頼する
  6. 出力した鍵ファイルのうち主鍵が含まれているものは安全な場所に移動させ、端末から消去する
$ gpg --armor --output all.keys --export-secret-keys      #(1)
$ gpg --armor --output sub.keys --export-secret-subkeys   #(2)
$ gpg --delete-secret-key 1111111111111111                #(3)
sec  ed25519/1111111111111111 2024-04-01 foo@example.com

Delete this key from the keyring? (y/N) y
This is a secret key! - really delete? (y/N) y

$ gpg --import sub.keys                                   #(4)
gpg: key 1111111111111111: public key "foo@example.com" imported
gpg: To migrate 'secring.gpg', with each smartcard, run: gpg --card-status
gpg: key 1111111111111111: secret key imported
gpg: Total number processed: 1
gpg:               imported: 1
gpg:       secret keys read: 1
gpg:   secret keys imported: 1

$ gpg --keyid-format LONG -K
/home/user/.gnupg/pubring.kbx
-------------------------------
sec#  ed25519/1111111111111111 2024-04-01 [C]
      FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
uid                 [ unknown] foo@example.com # <-- status: unknown
ssb   ed25519/2222222222222222 2024-04-01 [S]
ssb   ed25519/3333333333333333 2024-04-01 [S]

$ gpg --edit-key 1111111111111111                         #(5)
gpg> trust
Please decide how far you trust this user to correctly verify other users keys
(by looking at passports, checking fingerprints from different sources, etc.)

  1 = I don't know or won't say
  2 = I do NOT trust
  3 = I trust marginally
  4 = I trust fully
  5 = I trust ultimately
  m = back to the main menu

Your decision? 5                               # <- set ultimate
Do you really want to set this key to ultimate trust? (y/N) y
pub  ed25519/1111111111111111
     created: 2024-04-01  expires: never       usage: C
     trust: ultimate      validity: unknown
ssb  ed25519/2222222222222222 
     created: 2024-04-01  expires: never       usage: S
ssb  ed25519/3333333333333333 
     created: 2024-04-01  expires: never       usage: S
[ unknown] (1). foo@example.com

$ gpg --keyid-format LONG -K
/home/user/.gnupg/pubring.kbx
-------------------------------
sec#  ed25519/11111111111111112024-04-01 [C]
      FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
uid                 [ultimate] foo@example.com # <- status: ultimate
ssb   ed25519/2222222222222222 2024-04-01 [S]
ssb   ed25519/3333333333333333 2024-04-01 [S]

別端末に副鍵の秘密鍵をインポートする

複数の端末で同じ鍵を使いたい場合、鍵が入っている端末から副鍵をエクスポートし、別の端末でインポートする必要がある。

前のセクション「主鍵をエクスポートし、端末上から削除する」の手順 2 を実施して副鍵を取り出したあと、別の端末で手順 4 を実施する。

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

自分の署名を相手に検証してもらう / 自分宛のメッセージやデータを相手に暗号化してもらう、などの目的を達成するには、やり取りする相手の手元に自分の公開鍵が存在する必要がある。

$ gpg --armor --output foo.key --export 1111111111111111

公開鍵をインポートする

相手から鍵を受け取ったら、それを自分の環境にインポートすることで利用できるようになる。

$ gpg --import bar.key