Carpe Diem

備忘録

YubikeyにGPGの副鍵を転送する

概要

前回作ったGPGの副鍵をYubikeyに移してセキュアに管理できるようにします。

環境

前提知識

Yubikey 5が持つ機能

Yubikey 5には以下の機能があります。

f:id:quoll00:20220216100916p:plain

ref: ワンタイムパスワードトークンYubiKey |(株)ソフト技研

今回はその中でOpenPGPの機能を利用します。

Yubikeyの設定

KDFの設定

PINをハッシュ化してくれるKDFをまず設定します。

$ gpg --card-edit

Reader ...........: Yubico YubiKey OTP FIDO CCID
Application ID ...: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Application type .: OpenPGP
Version ..........: 3.4
Manufacturer .....: Yubico
Serial number ....: XXXXXXX
Name of cardholder: [未設定]
Language prefs ...: [未設定]
Salutation .......:
URL of public key : [未設定]
Login data .......: [未設定]
Signature PIN ....: 強制なし
Key attributes ...: rsa2048 rsa2048 rsa2048
Max. PIN lengths .: 127 127 127
PIN retry counter : 3 0 3
Signature counter : 0
KDF setting ......: off  # ここ
Signature key ....: [none]
Encryption key....: [none]
Authentication key: [none]
General key info..: [none]

gpg/card> admin
管理者コマンドが許可されています

gpg/card> kdf-setup
gpg/card> list

Reader ...........: Yubico YubiKey OTP FIDO CCID
Application ID ...: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Application type .: OpenPGP
Version ..........: 3.4
Manufacturer .....: Yubico
Serial number ....: XXXXXXX
Name of cardholder: [未設定]
Language prefs ...: [未設定]
Salutation .......:
URL of public key : [未設定]
Login data .......: [未設定]
Signature PIN ....: 強制なし
Key attributes ...: rsa2048 rsa2048 rsa2048
Max. PIN lengths .: 127 127 127
PIN retry counter : 3 0 3
Signature counter : 0
KDF setting ......: on # 変更された
Signature key ....: [none]
Encryption key....: [none]
Authentication key: [none]
General key info..: [none]

PINの変更

次にPINを変更します。

YubikeyのOpenPGP機能には通常のPINとAdminPINの2つがあります。
※FIDO2機能やPIV機能にもそれぞれPINがあるので注意

種類 初期値 用途 備考
PIN 123456 署名、復号、認証機能 6〜127文字(ASCII)
AdminPIN 12345678 PINのリセット、Reset Codeの変更、副鍵の追加や更新 8~127文字(ASCII)

基本的に使うのはPINですが、3回間違えるとブロックされるのでその場合はAdminPINを使ってアンブロックする必要があります。
AdminPINを3回間違えると鍵に設定した全てのGPGデータがなくなります。

またPINは6文字未満でも設定できますが、副鍵を使う時に反応してくれずAdminPINを入力する羽目になるので注意してください。

gpg/card> passwd
gpg: OpenPGPカードno. XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXを検出

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

あなたの選択は? 1

すると既存のPIN(初期値123456)と新しいPINを入力するよう求められます。

初期PIN

f:id:quoll00:20220217110013p:plain

新しいPIN

f:id:quoll00:20220217110056j:plain

AdminPINの変更

AdminPINも同様に更新します。

PIN changed.

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

あなたの選択は? 3
# ここで初期AdminPINと新しいAdminPINの入力を求められる
PIN changed.

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

あなたの選択は? Q

副鍵の転送

PINの設定が完了したので副鍵をYubikeyに転送します。

keytocardコマンドを使います。

$ gpg --edit-key $KEYID
gpg (GnuPG/MacGPG2) 2.2.32; 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.

秘密鍵が利用できます。

sec  nistp521/27131B8D68CE0EE9
     作成: 2022-02-14  有効期限: 無期限      利用法: C
     信用: 究極        有効性: 究極
ssb  nistp521/11AD0FF2F4BFD05E
     作成: 2022-02-14  有効期限: 無期限      利用法: E
ssb  nistp521/3B0879ECC6A5E40E
     作成: 2022-02-14  有効期限: 無期限      利用法: S
ssb  nistp521/48920981EDF04394
     作成: 2022-02-15  有効期限: 無期限      利用法: A
[  究極  ] (1). Junpei Tsuji <junpei.tsuji.ams@gmail.com>

# 鍵を選択。今回はまず暗号化鍵
gpg> key 1

# 選択するとその鍵に*が付く
sec  nistp521/27131B8D68CE0EE9
     作成: 2022-02-14  有効期限: 無期限      利用法: C
     信用: 究極        有効性: 究極
ssb* nistp521/11AD0FF2F4BFD05E
     作成: 2022-02-14  有効期限: 無期限      利用法: E
ssb  nistp521/3B0879ECC6A5E40E
     作成: 2022-02-14  有効期限: 無期限      利用法: S
ssb  nistp521/48920981EDF04394
     作成: 2022-02-15  有効期限: 無期限      利用法: A
[  究極  ] (1). Junpei Tsuji <junpei.tsuji.ams@gmail.com>

# Yubikeyへ転送
gpg> keytocard
鍵を保管する場所を選択してください:
   (2) 暗号化鍵
あなたの選択は? 2

sec  nistp521/27131B8D68CE0EE9
     作成: 2022-02-14  有効期限: 無期限      利用法: C
     信用: 究極        有効性: 究極
ssb* nistp521/11AD0FF2F4BFD05E
     作成: 2022-02-14  有効期限: 無期限      利用法: E
ssb  nistp521/3B0879ECC6A5E40E
     作成: 2022-02-14  有効期限: 無期限      利用法: S
ssb  nistp521/48920981EDF04394
     作成: 2022-02-15  有効期限: 無期限      利用法: A
[  究極  ] (1). Junpei Tsuji <junpei.tsuji.ams@gmail.com>

同様に他の鍵も転送します。

# まず選択を外す
gpg> key 1

# 次に転送する鍵を選択
gpg> key 2

sec  nistp521/27131B8D68CE0EE9
     作成: 2022-02-14  有効期限: 無期限      利用法: C
     信用: 究極        有効性: 究極
ssb  nistp521/11AD0FF2F4BFD05E
     作成: 2022-02-14  有効期限: 無期限      利用法: E
ssb* nistp521/3B0879ECC6A5E40E
     作成: 2022-02-14  有効期限: 無期限      利用法: S
ssb  nistp521/48920981EDF04394
     作成: 2022-02-15  有効期限: 無期限      利用法: A
[  究極  ] (1). Junpei Tsuji <junpei.tsuji.ams@gmail.com>

gpg> keytocard
鍵を保管する場所を選択してください:
   (1) 署名鍵
   (3) 認証鍵
あなたの選択は? 1

sec  nistp521/27131B8D68CE0EE9
     作成: 2022-02-14  有効期限: 無期限      利用法: C
     信用: 究極        有効性: 究極
ssb  nistp521/11AD0FF2F4BFD05E
     作成: 2022-02-14  有効期限: 無期限      利用法: E
ssb* nistp521/3B0879ECC6A5E40E
     作成: 2022-02-14  有効期限: 無期限      利用法: S
ssb  nistp521/48920981EDF04394
     作成: 2022-02-15  有効期限: 無期限      利用法: A
[  究極  ] (1). Junpei Tsuji <junpei.tsuji.ams@gmail.com>


gpg> key 2
gpg> key 3

sec  nistp521/27131B8D68CE0EE9
     作成: 2022-02-14  有効期限: 無期限      利用法: C
     信用: 究極        有効性: 究極
ssb  nistp521/11AD0FF2F4BFD05E
     作成: 2022-02-14  有効期限: 無期限      利用法: E
ssb  nistp521/3B0879ECC6A5E40E
     作成: 2022-02-14  有効期限: 無期限      利用法: S
ssb* nistp521/48920981EDF04394
     作成: 2022-02-15  有効期限: 無期限      利用法: A
[  究極  ] (1). Junpei Tsuji <junpei.tsuji.ams@gmail.com>

gpg> keytocard
鍵を保管する場所を選択してください:
   (3) 認証鍵
あなたの選択は? 3

後述してますが、スペアキーを作りたい場合は保存せずに一旦終了させます。

# スペアを作らない場合はsave。作る場合はsaveしないでquitし、スペアキーで同じ操作を繰り返す。
gpg> q
変更を保存しますか? (y/N) N
保存せずに終了しますか? (y/N) y

# スペアキーへ転送
...
gpg> save

確認

カードに転送すると、鍵一覧を表示した時に>マークが付くようになります。

$ gpg -K
/Users/jun06t/.gnupg/pubring.kbx
--------------------------------
sec#  nistp521 2022-02-14 [C]
      400397D054CBF0B4B0BD74AD27131B8D68CE0EE9
uid           [  究極  ] Junpei Tsuji <junpei.tsuji.ams@gmail.com>
ssb>  nistp521 2022-02-14 [E]
ssb>  nistp521 2022-02-14 [S]
ssb>  nistp521 2022-02-15 [A]

動作確認

Yubikeyなしの場合

$ gpg -u $KEYID -s test.txt
gpg: 署名に失敗しました: 操作がキャンセルされました

以下のようにYubikeyを挿入するようエラーが出ます。

f:id:quoll00:20220217111216p:plain

Yubikeyありの場合

$ gpg -u $KEYID -s test.txt

f:id:quoll00:20220217111339p:plain

正しいPINを入力すると署名できます。PINの入力は挿入後1度だけなのでそこまで手間でもないです。
抜いて改めて挿入した場合は再びPINの入力を求められます。

その他

その他気になった点を挙げていきます。

スペアキーの作り方

転送時に保存せず、もう一度同じ操作を繰り返すことでスペアキーを作成できます。

#!/bin/sh
#
# To make a duplicate Yubikey for GPG keys
# 1. Insert Yubikey1
# 2. Create keys/subkeys
# 3. Run keytocard to transfer keys to Yubikey1
# 4. QUIT WITHOUT SAVING!!!!! 
#
# This will leave the keys on the Yubikey but NOT change the 
# GPG keyring to point to the Yubikey1 with a stub
# 
# 5. Insert Yubikey2
# 6. Run keytocard to transfer keys to Yubikey2
# 7. QUIT and SAVE to make GPG point it's stubs to Yubikey2
#
# Running any decrypt, auth or sign will now ask you to insert Yubikey2
# To switch to Yubikey1 at any time run this script to force GPG 
# to repoint the key stubs to the inserted Yubikey

read -p "Insert the Yubikey you want to use ....  "   ignore
echo "Switching GPG to backup Yubikey ..."

gpg-connect-agent "scd serialno" "learn --force" /bye

YubiKey-Guide/switch-to-backup-yubikey at master · drduh/YubiKey-Guide · GitHub

その時点で複数のYubikeyを持っていなかった場合は、前回の記事を参考に

  1. 秘密鍵の削除
  2. 副鍵のインポート

を実行してスペアキーに同じ副鍵を転送してください。

ただしそうすると向き先がスペアキーになるので、次の内容を参考に向き先を変更してください。

Yubikeyが壊れた、海に落としたのでスペアキーを使う

スペアキーにも同じ副鍵を転送しましたが、マシンの副鍵はポインタの向き先として以前のYubikeyを見ています。
なのでスペアキーを挿しても以下のように怒られます。

f:id:quoll00:20220217064727p:plain

そこで以下のコマンドを打つとスペアキーを向くように変更できます。

$ gpg-connect-agent "scd serialno" "learn --force" /bye
S SERIALNO D2760001240103040006186501150000
OK
S PROGRESS learncard k 0 0
S PROGRESS learncard k 0 0
S PROGRESS learncard k 0 0
OK

別のマシンで使いたい

  1. 公開鍵のインポート
  2. スペアキーで行った向き先の再設定

を行うと別のマシンでもYubikeyでGPG操作をすることができます。

KDFを設定できない

KDFを設定しようと思ったところ以下のエラーが出ました。

gpg/card> kdf-setup
gpg: KDF設定のエラー: 使用条件が満たされていません

これはPINを設定する前に実行する必要があり、先に実行してしまった場合は以下コマンドでリセットが必要になります。

$ ykman openpgp reset

ref: https://support.yubico.com/hc/en-us/articles/360013761339-Resetting-the-OpenPGP-Application-on-the-YubiKey

まとめ

GPGの副鍵をYubikeyに転送し、Yubikey経由で署名等行うようにしました。

参考