YubiKeyのPIV
はじめに
YubiKeyはPIVという仕様に準拠している。Personal Identity Verification(PIV)はFIPS 201で定義された米国政府の標準。認証・署名・暗号化などの操作を行うことが出来る。SSHの公開鍵認証に使用することも出来る。OpenPGPを使用してもSSHの公開鍵認証は可能だが、こちらはPINの要求頻度を鍵スロットごとに柔軟に変更したり、証明書の保存が可能なため組織的な利用に使いやすいといった利点がある。NFCからの利用も可能。 PINについて
PINには三種類あり、それぞれ利用用途が異なる。
PIN
: 署名作成や認証時に使用する。6バイト以上8バイト以内(ASCIIであることが指定されているため、実質6文字以上8文字以内)。指定の回数間違えるとロックが掛かり、PUKを使用しないと解除できない。
移植性の観点から10進数のみにすることが推奨されてるが、オプションとしてセキュアにするために複数種類の文字の使用を強制することも出来るらしい(矛盾してね?)
あと有効期限を設定することも出来るみたい。
デフォルトは 123456
PUK
: ロックが掛かったときや、PUK自体の変更を行う際に使用する。指定の回数間違えると完全にロックが掛かり、ファクトリーリセットが必要。
制限はPINと同じで6バイト以上8バイト以内だが、ASCIIとは限らない(任意のバイナリ値が使用可能)。あくまでYubiKeyが任意のバイナリ値を受け入れるだけで、ykmanなどで設定する際はASCIIで設定する。
デフォルトは 12345678 (ASCII)
Management Key
: 鍵ペアの作成や鍵のインポートなど管理系の操作をする際に必要。デフォルトでは24バイトのTDESだが、5.4.2以降は16/24/32バイトのAESにすることも出来る。一般にAESのほうが強固なのでAESを使用することをおすすめする。
デフォルトはTDESの 0x010203040506070801020304050607080102030405060708 (バイナリ)
また、管理系の操作時にManagement Keyを要求しないように設定することも出来る(Manegement Keyは長くて覚えづらいので)。これは管理キーをPINで保護された領域に保存することによって実現している(実はもう一つPINからManagement Keyを割り出す事によって実現する方式もあるが、非推奨)。
なお、PINのみのモードに設定すると、PUKによるPINの変更やリセットが出来なくなる。理由はPIVの運用形態として、PINとManagement Keyをエンドユーザーが持ち、PUKを管理者が持つという形を取る。この場合は悪意のある管理者はPINが変更できる以上の損害を与えることは出来ないので安全である。しかし、PINのみのモードではPINの変更によってManagement Keyの制御もできてしまう。以上のことからPINのみのモードの場合はPUKがブロックされるようになる。これはPINを忘れると回復が出来なくなることを意味するので注意が必要。
スロットについて
スロットはデータを格納する場所のこと。PIV標準では25スロットが指定されており、YubiKeyではファームウェアのバージョンに応じて最大28スロットが使用できる。スロット一つ一つに番号がついていて、番号の16進数表現で識別される。スロットごとに格納されるデータの種類と用途が異なる。また、PINの入力頻度も異なる。
9A
: システムログイン時のユーザー認証に用いる。RSA/ECC鍵と証明書が入る。PINはセッション単位で保存される。
9C
: ファイルへの署名に用いる。RSA/ECC鍵と証明書が入る。PINは都度要求される。
9D
: ファイルの暗号化/復号に用いる。RSA/ECC鍵と証明書が入る。PINはセッション単位で保存される。
9E
: カード認証(NFCとかを使った入館証のイメージ?)に用いる。RSA/ECC鍵と証明書が入る。PINは必要ではない。
F9
: 他スロットの鍵がYubiKeyによって生成されたことを証明するために用いる。RSA鍵と証明書が入る。PIV非標準。
82
: 9A〜9Eまでの鍵が変わると以前の鍵や証明書がここに入る。
83
: 9A〜9Eまでの鍵が変わると82に入っていたデータがここに移動する。
84
: 9A〜9Eまでの鍵が変わると83に入っていたデータがここに移動する。
85〜95
: 上と同様
PINとタッチポリシーについて
9A〜9EまでのスロットにはそれぞれPINの入力頻度とタッチポリシーが設定できる。デフォルトのPINの設定は上記の通り、タッチポリシーは全て使用しないになっているが、これを変更することも出来る。この変更はそれぞれ鍵の生成/インポート時のみ可能。
PINの入力頻度は以下から選択できる。
DEFAULT
: スロットのデフォルト設定に戻す。
NEVER
: PINを聞かない。この場合安全性が著しく低下することに留意する。
ONCE
: PCにYubiKeyを挿してからPINを一度だけ聞く。それ以降は鍵を抜くまでPINは聞かれない。
ALWAYS
: 鍵を使用するたびにPINを聞く。最も安全。
タッチポリシーは以下から選択できる。
DEFAULT
: スロットのデフォルト設定に戻す。(デフォルトでタッチは使用しないため、実質NEVERと同じ)
NEVER
: タッチは要求されない。
ALWAYS
: 鍵を使用するたびにタッチを要求する。
CACHED
: 鍵を使用するたびにタッチを要求するが、15秒間キャッシュされる。
PINの試行回数変更
試行回数を変えるとPINとPUKがリセットされてしまうので変える場合は先に設定しておく。数値は左からPIN PUKの試行回数。デフォルトは3 3。
code:sh
ykman piv access set-retries 5 10
PIN変更
PINの変更
code:sh
ykman piv access change-pin
PUKの変更
code:sh
ykman piv access change-puk
Management Keyの変更
code:sh
ykman piv access change-management-key --algorithm AES256 --generate --touch --protect
解説:
--algorithm AES256
: 鍵のアルゴリズムを指定する。TDSとAES128/192/256から選べるが、一番強いのはAES256。
--generate
: 鍵を自動で生成する。--protectを付けない場合は生成された鍵は標準出力される。
--touch
: Management Key使用時にYubiKeyへのタッチが必要になる。
--protect
: Management KeyをPINで保護し、PINのみのモードにする。PINで全てをこなすので、安全性は下がることに留意する。
鍵生成
鍵はYubiKey内で生成したほうがF9のYubiKeyで生成したという証明書を利用できるのでおすすめ。鍵のアルゴリズムはRSA1024/RSA2048/ECCP256/ECCP384から選べる。少なくともRSA1024は論外なので使用しないほうがよい。オプションの後は鍵のスロットと公開鍵の出力先ファイル名を指定する。
code:sh
# 公開鍵のファイル名はあくまで例
ykman piv keys generate --algorithm ECCP384 9a 9a-<SERIAL NO>.pem
追加のオプション:
--pin-policy <POLICY>
PINの入力頻度を設定する。
--touch-policy <POLICY>
タッチポリシーを設定する。
自己署名証明書発行
組織的な管理を想定していなかったり、プライベートCAを運用していない場合は、自己署名証明書を鍵の証明書とする。ハッシュアルゴリズムはSHA256/SHA384/SHA512から選べる。また、証明書に含めるSubjectの文字列は必須で必要。オプションの後は鍵のスロットと公開鍵のファイル名を指定する。
code:sh
# CNはあくまで例
ykman piv certificates generate --hash-algorithm SHA512 --subject 'CN=YubiKey <SERIAL NO>' 9a 9a-<SERIAL NO>.pem
YubiKey内部の鍵ペアを使用して証明書発行
9Fスロットに入っている鍵ペアを使用して他のスロットの鍵に対して証明書を発行することが出来る。この証明書はYubiKeyで生成した鍵にしか発行することが出来ない。デフォルトで9Fスロットに入っている鍵ペアはYubico PIV CAで署名された証明書が入っており、先にこの証明書を取り出しておくことによって確実にこのYubiKeyから生成された鍵であることを証明できる。なお、このスロットはファクトリーリセットをかけても鍵ペアが消えることはない。ただし上書きは可能で、上書きしてしまうとYubico PIV CAで署名された証明書と鍵ペアは二度と手に入らないので注意。
証明書を発行する鍵のスロットと証明書のファイル名を指定する。
code:sh
# 証明書のファイル名は例
ykman piv keys attest 9a 9a-attest-<SERIAL NO>.crt
SSH鍵として扱う
yubico-piv-toolやOpenSCをインストールすると付いてくるライブラリを用いてPIV内の鍵からSSH公開鍵を出力することができる。
yubico-piv-toolで付いてくるlibykcs11は、
Debianベースの場合: /usr/local/lib/libykcs11
macOSの場合: /usr/local/lib/libykcs11.dylib
OpenSCの場合はopensc-pkcs11を使う。
code:sh
ssh-kengen -D /path/to/libykcs11 -e
なお、鍵のアルゴリズムをECC P-256/384にしている場合、比較的新しいOpenSSHで無いと対応していない場合がある。OpenSSH 8.0p1(8.6?)で対応したようだが、macOSでは8.6p1であるにも関わらず使用できないため、詳細は不明。特にmacOSの場合は標準のOpenSSHは未対応(執筆時点)なので、HomeBrewからOpenSSHをインストールしておくこと。 コンフィグファイルでもライブラリの場所を指定しておく。
code:.ssh/config
Host *
PKCS11Provider /path/tp/libykcs11
後は普通にSSHすれば勝手に使用される。PINやタッチポリシーはスロットに設定したものが適用される。GnuPGなどのssh-agentを使用していて、GnuPG側の鍵とPIV側の鍵のどちらも使用できる場合は先にGnuPG側の鍵を使用しようとする。
ファクトリーリセット
YubiKeyのPIV関連の設定を全てリセットし、工場出荷状態に戻す。なお、このファクトリーリセットはYubiKeyの中のPIV関連の設定のみであり、他のOpenPGPやFIDO U2F/FIDO2などの機能には一切影響を与えない。
code:sh
ykman piv reset