Yubikey5を手に入れたのでGPGを使ってみる(1/2)(GPG key作成編)
Yubikeyとは
YubiKeyとはこのような見た目で、アメリカ・スウェーデンを拠点とするYubico社が開発した認証デバイス。
特徴として、海底48mに沈めて二ヶ月放置しても、洗濯乾燥機に突っ込んでも壊れない堅牢性と分解・解析に対する耐タンパ性を持っている。また、Yubikeyにデータを書き込むことは簡単にできるが、読み出すことは一切できない。そのため、秘密鍵などを保管するのに適している。
機能
購入したYubikey 5C NFCには以下の機能がある
- FIDO2
- OTP
- U2F
- OATH
- PIV (Smart Card)
- OpenPGP
Yubikey 5C NFCではOpenPGPにてECC(楕円曲線)に対応しているため、それを使用する。
GnuPGとは
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である 。
右端列の「強度」は鍵長ではなく,セキュリティ強度なのでご注意を。
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のガイドは以下のリポジトリがすごく参考になる。 と言うか本記事はこのガイドを元に記述している。
Yubikeyの公式ドキュメント
作成の流れ
作成する環境はUbuntuのLive Imageを使用する。
GPGにはmasterキーとそれのsubキーの2つの種類のキーが存在する。 masterキーは絶対秘密にしておかなければならない最重要のキーであり、普段はオフラインにて安全に保存する必要がある。 masterキーを使用するときは新たなsubキーを作成する時や、キーを失効させたりするときのみである。 またそれぞれのキーには機能(例えば証明、署名、暗号化、認証などである)があり、各機能毎にキーを分ける方が良いとされる。
- masterキー(証明)を作成
- subキー(署名、暗号化、認証のそれぞれ)を作成
- master, subの秘密鍵のエクスポート
- 失効証明書の作成
- 鍵のバックアップ
- 公開鍵をエクスポート
- subキーの秘密鍵をYubikeyに移動させる
- クリーンアップ
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
証明書ファイルは、メインバックアップが失敗した場合に取得できるように、別場所に保存(または印刷)する必要がある。
続きはこちら