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で登録されたメールアドレスにする必要がある。 GitHubやTwitterと連携したい場合においてはその辺りを考慮した上で選ぶとよい。
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というサービスがあり、ここで公開鍵を登録した上で、TwitterやGitHubのアカウントを連携することができる。
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がつく
- 人と暗号化されたテキストをやりとりする。
- メールに署名をする。
- passを用いてlastpassなどのプロプライエタリなパスワードマネージャーから脱却する。