laft’s diary

備忘録か日記

GPGで遊んでみた話(WSL2, WSLg)

GPG、認知はしてたけどちゃんと使ったことなかったので鍵を作ってkeybaseに登録してyubikeyに副鍵を入れるところまでやった(WSL2, WSLg環境)。

再現できるように手順をメモしておく。

GPGとは

PGP(Pretty Good Privacy)というソフトウェアが存在していた。 これは公開鍵暗号方式を用いて暗号化を行うソフトウェアである。

現在はRFCにてOpen PGPとして規格化されており、現在はRFC4880となっている。 GPG(GNU Privacy Guard)はOpen PGPに準拠したフリーソフトウェアである。

GPGで主鍵を生成

GPG自体は普通にUbuntuにプリインストールされているので、とりあえず主鍵を生成する。

$ gpg --full-gen-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)
  (13) Existing key
  (14) Existing key from card
Your selection?

楕円曲線を使いたいので11を選択(もちろんRSAでもよい)。 (expertオプションをつけてないと楕円曲線は表示されない。)

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?

主鍵にはCertify(他の鍵への署名)の機能だけを与え、他の機能は主鍵の署名がついた副鍵で行う。 そのため、ここでは Current allowed actions にCertifyだけが残るようにsを1回入力し、finishする。

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

好きな楕円曲線を選ぶ。SSHとかでも使われている1で良さそう。

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

するとReal nameとemailを聞かれるので、適当に答える。 本来の用途からすると実名が望ましいが、公開鍵のメタデータとして公開される。 emailについても、githubでverifyしてもらうには、githubで登録されたメールアドレスにする必要がある。 GitHubTwitterと連携したい場合においてはその辺りを考慮した上で選ぶとよい。

fingerprintをそのままに後から追加したり変更したりすることは可能なので、そこまで悩む必要もないかも。 Commentも聞かれるが空で良い。

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

Real name: laft2
Email address: laft@example.com
Comment:
You selected this USER-ID:
    "laft2 <laft@example.com>"

Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? o

Okayのoを入力したら、後は秘密鍵パスフレーズを設定して終わり。

副鍵の生成

主鍵は盗まれたりすると本当に終わりなので、基本的には主鍵によって署名された副鍵を用いて署名、復号(暗号化)、認証を行う。 機能ごとに副鍵を生成するが、手順はほぼ同じなので、ここでは署名を例に行う。

副鍵は主鍵に紐づけて生成するので、主鍵のeditから行う。 以下laftとなっているところは適宜自分のメールアドレスのprefixを書けばよい。 他の主鍵と識別可能であればよいので、初めて作るなら1文字でも大丈夫なはず。

$ gpg --expert --edit-key laft

Secret key is available.

sec  ed25519/XXXXXXXXXXXXXXXX
     created: yyyy-mm-dd  expires: never       usage: C
     trust: ultimate      validity: ultimate
[ultimate] (1). laft2 <laft@example.com>

gpg>

となっているはずなので、addkeyする。どのようなコマンドが存在するかはhelpと入力することで確認できる。

gpg> addkey

すると主鍵の時のように暗号化アルゴリズムを選択する画面に入るので、好きなアルゴリズムを選ぶ。 ここでは署名onlyな楕円曲線を選び、25519を選ぶ。

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? 1

生存期間を選ぶ。主鍵と異なり、副鍵を更新するには主鍵の秘密鍵が必要である。 ここでは主鍵同様に0にするが、きちんと設定する方が望ましい。

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.

これで完成。暗号用の副鍵も同様に生成しておく。(アルゴリズムを選ぶときに12のencrypt onlyな楕円曲線暗号を選択すればよい。)

最後にsaveして抜ける。

gpg> save

gpg -k と打つと公開鍵の情報を確認できる。(-Kオプションで秘密鍵の確認もできる。)

$ gpg -k
/home/user/.gnupg/pubring.kbx
-----------------------------
pub   ed25519 yyyy-mm-dd [C]
      XXXXXXXXXXXXXXXXXXXXXXXXX
uid           [ultimate] laft2 <laft@example.com>
sub   ed25519 yyyy-mm-dd [S]
sub   cv25519 yyyy-mm-dd [E]

主鍵をオフラインストレージに移す

GPGの秘密鍵をオンラインなデバイスに置いておくのは危険なので、オフラインストレージに移した上で削除する。 基本的な機能は副鍵が行ってくれるので、主鍵の秘密鍵を削除しておいても問題ない。 新たに副鍵を作ったり、主鍵の公開鍵の情報を変更したい場合に必要なので無くさないようにすること(自戒)。

$ gpg -K # 秘密鍵を確認
/home/user/.gnupg/pubring.kbx
-----------------------------
sec ed25519 yyyy-mm-dd [C]
      XXXXXXXXXXXXXXXXXXXXXXXXX
uid           [ultimate] laft2 <laft@example.com>
ssb   ed25519 yyyy-mm-dd [S]
ssb   cv25519 yyyy-mm-dd [E]

秘密鍵をexportする。aオプションをつけるとasciiで出力されてうれしい。(つけないとバイナリで出力されてかなしい。)

$ gpg --export-secret-keys -a laft > secret-key.asc

これをオフラインストレージ(USBメモリなど)に保存したり、QRコードエンコードして家に保存したりするとよいらしい。 (gpg のリリース 2.1からはデフォルトで秘密鍵のパスフレーズによる暗号化がなされるようになっているため、ここから更に暗号化する必要はそれほどない。)

保存したら、今つくったものを消す。

$ shred -u secret-key.asc

その後、主鍵の秘密鍵だけを削除する。主鍵の秘密鍵だけを削除するには、削除のダイアログで「主鍵を削除しますか」にyと答え、その後の「副鍵を削除しますか」にnと答える必要がある。

$gpg --delete-secret-keys laft

<keyの情報>

Delete this key from the keyring? (y/N) y
This is a secret key! - really delete? (y/N) y
(私の環境はWSLgなので、ここで2回GUIダイアログが出現する。1回目にdelete keyと答え、2回目はNoと答える)
gpg: deleting secret subkey failed: Operation cancelled
gpg: laft: delete key failed: Operation cancelled

再度秘密鍵を確認すると、鍵の後ろに"#"がついている。 主鍵だけについていれば成功。

$ gpg -K # 秘密鍵を確認
/home/user/.gnupg/pubring.kbx
-----------------------------
sec# ed25519 yyyy-mm-dd [C]
      XXXXXXXXXXXXXXXXXXXXXXXXX
uid           [ultimate] laft2 <laft@example.com>
ssb   ed25519 yyyy-mm-dd [S]
ssb   cv25519 yyyy-mm-dd [E]

ちなみに、オフラインストレージなどに保存した秘密鍵をimportするときは以下のコマンドを実行すればよい。

$ gpg --import secret-key.asc

ここまででgpgの事前設定は全て完了した。 公開鍵は公開しないと意味がないので、その方法を紹介する。

keybaseに鍵を登録する

keybase.ioというサービスがあり、ここで公開鍵を登録した上で、TwitterGitHubのアカウントを連携することができる。

keybase上で他人をフォローすることは、その人の公開鍵を信頼することを意味し、 その人がフォローしている人の公開鍵についても、程度の差はあれど信頼することができる。

このように、確実な知り合いをフォローすることで信頼の輪(Web of Trust)を広げていくことができる。何hopまで信頼するかはその人の裁量しだい。

keybaseのインストール

keybase.io の通りに進めていく。

2023/2/17時点では以下のコマンドを実行すればよい。

curl --remote-name https://prerelease.keybase.io/keybase_amd64.deb
sudo apt install ./keybase_amd64.deb
run_keybase

run_keybaseを実行すると、当環境(WSLg)ではGUIのkeybaseアプリが起動する。

sign up

$ keybase signup

これで案内が出るのでその通りに進める。

keybaseにGitHubを登録

GUIのkeybaseアプリのSettings > Your account > Website login からkeybase.io にログインする。

ログインするとtwitterが設定できそうなマークが画面中央にあると思うので、そこから案内に従って連携すればOK。 Gistを用いて連携する。

yubikeyに副鍵の秘密鍵をexport

yubikey持ってて遊びたい人用コンテンツです。

これをやると、yubikeyがささっている時だけ秘密鍵を使うことができるようになる。 また、普段使っていないデバイスでもyubikeyを挿すことで、その秘密鍵を利用できる。

先に言っておくと、WSLからyubikeyを常用するのは若干面倒なので、yubikey用の鍵と常用する鍵は別でもいいかもしれない。(私はそうした。)

yubikeyをWSLから認識させる

普通に指すとWSL側から認識してくれないので、Windowsにusbipdをインストールする(参考)。

# (powershell)
$ winget install --interactive --exact dorssel.usbipd-win

インストールしたら、管理者モードでpowershellを開いて、yubikeyっぽいのを探す。

# (powershell 管理者モード)
$ usbipd wsl list
BUSID  VID:PID    DEVICE                                                        STATE
X-X    XXXX:XXXX  USB 入力デバイス, Microsoft Usbccid Smartcard Reader (WUDF)   Not attached

これがyubikeyっぽいので、このBUSIDを指定してWSLに渡してあげる。

# (powershell 管理者モード)
$ usbipd wsl attach --busid X-X

これをやると、WSL側からyubikeyが見えるようになる。(Windows側からは見えなくなる)

# (WSL)
$ lsusb
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 005: ID 1050:0407 Yubico.com Yubikey 4/5 OTP+U2F+CCID
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

が、このままだとGPGが認識してくれないので、以下のコマンドを入力する必要がある(参考)。

sudo apt install scdaemon
sudo apt install pcscd
sudo service pcscd start

これで見えるようになるはず。gpg --card-statusを実行して以下のようになっていれば大丈夫。

$ gpg --card-status
Reader ...........: Yubico YubiKey OTP FIDO CCID
Application ID ...: 
Application type .: OpenPGP
Version ..........: 3.4
Manufacturer .....: Yubico
...

yubikeyに焼く

ここまでできたらgpg --edit-cardから実際にyubikeyに焼いていく(参考)。

まずは初期設定から。

$ gpg --edit-card
(yubikeyの情報と鍵の情報)

gpg/card> admin
Admin commands are allowed

gpg/card> kdf-setup # 初回のみ。
gpg/card> passwd # PIN変更。初回のみ。
gpg: OpenPGP card no. XXXX detected

1 - change PIN
2 - unblock PIN
3 - change Admin PIN
4 - set the Reset Code
Q - quit

Your selection?

PINとAdmin PINの変更を行う。初期PINは123456、初期Admin PINは12345678

初期設定が終わったら、一旦gpgから抜けてgpg --edit-key laftする。

$ gpg --edit-key laft
pub  ed25519/XXXXXXXXX
     created: 2023-02-16  expires: never       usage: C
     trust: ultimate      validity: ultimate
ssb  ed25519/XXXXXXXXXXXXX
     created: 2023-02-17  expires: never       usage: S
ssb  cv25519/XXXXXXXXXXXXX
     created: 2023-02-17  expires: never       usage: E
gpg> key 1 # 副鍵の1番目を選択
pub  ed25519/XXXXXXXXX
     created: 2023-02-16  expires: never       usage: C
     trust: ultimate      validity: ultimate
ssb*  ed25519/XXXXXXXXXXXXX
     created: 2023-02-17  expires: never       usage: S
ssb  cv25519/XXXXXXXXXXXXX
     created: 2023-02-17  expires: never       usage: E

key Xで上からX番目の副鍵を選択できる。 選択すると*がつく。

この状態でkeytocardする

gpg> keytocard
Please select where to store the key:
   (1) Signature key
   (3) Authentication key
Your selection? 1

で移せる。暗号用の鍵についても同様。 認証用の鍵を別途作っておいてAuthentication keyとしてyubikeyに秘密鍵を移すこともできる。

全ての操作が終わったら、saveすることでlocalから秘密鍵を削除される。

$ gpg -K
sec# ed25519 yyyy-mm-dd [C]
      XXXXXXXXXXXXXXXXXXXXXXXXX
uid           [ultimate] laft2 <laft@example.com>
ssb>  ed25519 yyyy-mm-dd [S]
ssb>  cv25519 yyyy-mm-dd [E]

smart cardに移された鍵は>マークがつく。

これで全て完了。

GPGの使い道

  • gitのcommitに署名する。
    • GitHubに公開鍵を登録しておくと、コミットにVerifiedがつく
      verified in GitHub
  • 人と暗号化されたテキストをやりとりする。
  • メールに署名をする。
  • passを用いてlastpassなどのプロプライエタリなパスワードマネージャーから脱却する。

参考文献