Yubikey5を手に入れたのでGPGを使ってみる(1/2)(GPG key作成編)

Yubikeyとは

support.yubico.com

YubiKeyとはこのような見た目で、アメリカ・スウェーデンを拠点とするYubico社が開発した認証デバイス。

特徴として、海底48mに沈めて二ヶ月放置しても、洗濯乾燥機に突っ込んでも壊れない堅牢性と分解・解析に対する耐タンパ性を持っている。また、Yubikeyにデータを書き込むことは簡単にできるが、読み出すことは一切できない。そのため、秘密鍵などを保管するのに適している。

機能

購入したYubikey 5C NFCには以下の機能がある

  • FIDO2
  • OTP
  • U2F
  • OATH
  • PIV (Smart Card)
  • OpenPGP

Yubikey 5C NFCではOpenPGPにてECC(楕円曲線)に対応しているため、それを使用する。

GnuPGとは

text.baldanders.info

GnuPG (GNU Privacy Guard) は OpenPGP 実装のひとつで,現在は以下の RFC に準拠している。

  • RFC 4880 - OpenPGP Message Format
  • RFC 5581 - The Camellia Cipher in OpenPGP
  • RFC 6637 - Elliptic Curve Cryptography (ECC) in OpenPGP

OpenPGPの源流であるPGP (Pretty Good Privacy) は、Philip Zimmermannが1991年に開発した暗号ソフトウェア。 PGPにはそれが公開特許ではなく複雑な特許権問題が絡んでいるという問題があった。 そのため、当時の PGP の仕様を知財的に安全なものとして再構成したのが OpenPGPである 。

text.baldanders.info

右端列の「強度」は鍵長ではなく,セキュリティ強度なのでご注意を。

SECG/NIST 推奨パラメータ

GnuPG SECG NIST アルゴリズム 強度 bits
nistp256 secp256r1 NIST curve P-256 ECDH, ECDSA 128
nistp384 secp384r1 NIST curve P-384 ECDH, ECDSA 192
nistp521 secp521r1 NIST curve P-521 ECDH, ECDSA 256
secp256k1 secp256k1 ECDH, ECDSA 128

Yubikey 5C NFCが対応しているアルゴリズムでセキュリティ強度が一番長い secp521r1 を使う。

GPGキーの作成

Yubikey本体でキーの作成も出来るが、取り出すことが出来ないので、Yubikeyを紛失した場合終わるため、後からインポートする方法をとる。

Yubikeyのガイドは以下のリポジトリがすごく参考になる。 と言うか本記事はこのガイドを元に記述している。

github.com

Yubikeyの公式ドキュメント

developers.yubico.com

作成の流れ

作成する環境はUbuntuのLive Imageを使用する。

GPGにはmasterキーとそれのsubキーの2つの種類のキーが存在する。 masterキーは絶対秘密にしておかなければならない最重要のキーであり、普段はオフラインにて安全に保存する必要がある。 masterキーを使用するときは新たなsubキーを作成する時や、キーを失効させたりするときのみである。 またそれぞれのキーには機能(例えば証明、署名、暗号化、認証などである)があり、各機能毎にキーを分ける方が良いとされる。

  1. masterキー(証明)を作成
  2. subキー(署名、暗号化、認証のそれぞれ)を作成
  3. master, subの秘密鍵のエクスポート
  4. 失効証明書の作成
  5. 鍵のバックアップ
  6. 公開鍵をエクスポート
  7. subキーの秘密鍵をYubikeyに移動させる
  8. クリーンアップ

3,4では暗号化したボリュームにコピーをする(今回はmicro SDカードを用いた)

つまり、masterキーはオフラインで安全にバックアップをとり、普段使用するYubikeyには各種subキーを保管する

依存ソフトのインストール

/etc/apt/sources.list の各行に universe multiverseを追加してから以下を行う。

$ sudo apt update
$ sudo apt -y install wget gnupg2 gnupg-agent cryptsetup scdaemon pcscd secure-delete

一時ディレクトリを作成する

$ export GNUPGHOME=$(mktemp -d)

Masterキーの作成

masterキーのパスフレーズの作成

$ gpg --gen-random --armor 0 24
Q0ujl1x35gacX95okzlABZ93aHOBvZJl

機能が Certify だけになるようにする。 masterキーは有効期限は無期限にしてオフラインで管理する方がいいみたい。

11 -> S -> Q -> 5 -> 0 -> y -> 名前 -> メールアドレス -> コメント(あれば) と入力して先ほど作成したパスフレーズを入力する。

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

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? 5
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: <メールアドレス>
Comment:
You selected this USER-ID:
    "<名前> <メールアドレス>"

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: /tmp.nqKpgHfYNN/trustdb.gpg: trustdb created
gpg: key BF8A708B020A19BB marked as ultimately trusted
gpg: directory '/tmp/tmp.nqKpgHfYNN/openpgp-revocs.d' created
gpg: revocation certificate stored as '/tmp.nqKpgHfYNN/openpgp-revocs.d/D6FCE147DE91797391B2D70BBF8A708B020A19BB.rev'
public and secret key created and signed.

pub   nistp521 2020-12-09 [C]
      D6FCE147DE91797391B2D70BBF8A708B020A19BB
uid                      <名前> <メールアドレス>

gpg: key BF8A708B020A19BB marked as ultimately trusted

キーIDは後で使うので環境変数にセットしておく

$ export KEYID=BF8A708B020A19BB 

Subキーを作成する

今回は簡略化のためsubキーも有効期限を無期限としているが本来は有効期限を設定した方が良い。

$ gpg --expert --edit-key $KEYID
gpg (GnuPG) 2.2.20; Copyright (C) 2020 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.

gpg: checking the trustdb
gpg: marginals needed: 3  completes needed: 1  trust model: pgp
gpg: depth: 0  valid:   1  signed:   0  trust: 0-, 0q, 0n, 0m, 0f, 1u
sec  nistp521/BF8A708B020A19BB
     created: 2020-12-09  expires: never       usage: C
     trust: ultimate      validity: ultimate
[ultimate] (1). <名前> <メールアドレス>

gpg>

Signing (署名)

署名のみのsubキーを作成する。

10 -> 5 -> 0 -> y -> y と入力して先ほど作成したパスフレーズを入力する。

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)
  (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? 5
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  nistp521/BF8A708B020A19BB
     created: 2020-12-09  expires: never       usage: C
     trust: ultimate      validity: ultimate
ssb  nistp521/983982062E1BB33D
     created: 2020-12-09  expires: never       usage: S
[ultimate] (1). <名前> <メールアドレス>

Encryption (暗号化)

暗号化のみのサブキーを作成する

12 -> 5 -> 0 -> y -> y と入力して先ほど作成したパスフレーズを入力する。

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)
  (11) ECC (set your own capabilities)
  (12) ECC (encrypt only)
  (13) Existing key
  (14) Existing key from card
Your selection? 12
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? 5
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  nistp521/BF8A708B020A19BB
     created: 2020-12-09  expires: never       usage: C
     trust: ultimate      validity: ultimate
ssb  nistp521/983982062E1BB33D
     created: 2020-12-09  expires: never       usage: S
ssb  nistp521/008734F36B087C1C
     created: 2020-12-09  expires: never       usage: E
[ultimate] (1).  <名前> <メールアドレス>

Authentication (認証)

認証のみのsubキーを作成する。 認証のみの機能は一覧にないため、自分で機能の選択をして認証のみにする。

11 -> A -> S -> Q -> 5 -> 0 -> y -> y と入力して先ほど作成したパスフレーズを入力する。

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)
  (11) ECC (set your own capabilities)
  (12) ECC (encrypt only)
  (13) Existing key
  (14) Existing key from card
Your selection? 11

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

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

Your selection? A

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

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

Your selection? S

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

   (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? 5
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  nistp521/BF8A708B020A19BB
     created: 2020-12-09  expires: never       usage: C
     trust: ultimate      validity: ultimate
ssb  nistp521/983982062E1BB33D
     created: 2020-12-09  expires: never       usage: S
ssb  nistp521/008734F36B087C1C
     created: 2020-12-09  expires: never       usage: E
ssb  nistp521/26BAE38657860920
     created: 2020-12-09  expires: never       usage: A
[ultimate] (1). <名前> <メールアドレス>

gpg>

保存して終了する

gpg> save

検証する

-K オプションを渡すことでGPGが認識している秘密鍵をリストアップしてくれる。

$ gpg -K
/tmp/tmp.nqKpgHfYNN/pubring.kbx
------------------------------
sec   nistp521 2020-12-09 [C]
      D6FCE147DE91797391B2D70BBF8A708B020A19BB
uid           [ultimate] <名前> <メールアドレス>
ssb   nistp521 2020-12-09 [S]
ssb   nistp521 2020-12-09 [E]
ssb   nistp521 2020-12-09 [A]

ちなみに左の sec とか ssb とかはそれぞれ以下を表している。

  • sec => SECret key
  • ssb => Secret SuBkey
  • pub => PUBlic key
  • sub => public SUBkey

秘密鍵をエクスポートする

マスターキーとサブキーは、エクスポート時にパスフレーズで暗号化される。

$ gpg --armor --export-secret-keys $KEYID > $GNUPGHOME/master.key

$ gpg --armor --export-secret-subkeys $KEYID > $GNUPGHOME/sub.key

master.key は新たなsubキーを作成するときや、有効期限を更新するときにインポートして使うためにエクスポートしている。

失効証明書を作成する

マスターキーをバックアップして安全な場所に保存するが、マスターキーを紛失したり、バックアップが失敗したりする可能性をがあるため失効証明書は必要。

y -> 0 -> 追加の説明(あれば) -> y と入力して先ほど作成したパスフレーズを入力する。

$ gpg --output $GNUPGHOME/revoke.asc --gen-revoke $KEYID

sec  nistp521/BF8A708B020A19BB 2020-12-09  <名前> <メールアドレス>

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? 0
Enter an optional description; end it with an empty line:
>
Reason for revocation: No reason specified
(No description given)
Is this okay? (y/N) y
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!

この revoke.asc 証明書ファイルは、メインバックアップが失敗した場合に取得できるように、別場所に保存(または印刷)する必要がある。

続きはこちら

blog.akashisn.info