SSH用の鍵管理にYubiKeyを使ってみた

#YubiKeyとは
[yubico](https://www.yubico.com/yubikey/?lang=ja)が販売している公開鍵管理やMFAとして利用できるハードウェアトークン。
FIDO2 U2Fに準拠しているほか、PIV対応、TOTPなどの多要素認証機能など、豊富な機能が魅力。

内部に秘密鍵を保持でき、外部に書き出せないという特徴があるため、セキュアに鍵管理を行うことができる。
秘密鍵と公開鍵のKeyPairはYubiKey内部で生成したり(秘密鍵の外部出力不要)、既存のKeyPairをImportすることも可能。

**活用方法の例**
 - Windowsのログイン認証時に、YubiKeyの差込み＋タッチ必須にする(多要素認証)
 - PCに秘密鍵をコピーすることなくSSH接続に公開鍵暗号方式を利用する

接続形態(USB Type-A/USB Type-C/NFC)や機能の異なる複数製品が販売されている。
![接続形態や機能の異なる複数製品がある](https://www.yubico.com/wp-content/uploads/2021/05/YK5FIPS-Family-overhead-ko-final-small.png)

#実現したい構成
####YubiKeyのSlotに複数の秘密鍵を格納して、SSH接続するときに自動的に秘密鍵を選択させたい。####
![Composition.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245439/d7a3d16c-d4d7-0604-70ae-c9805f9adec0.jpeg)

#今回やったこと
 - YubiKeyの初期設定
 - SSH接続するときに利用する、複数の秘密鍵をYubiKeyのSlotにインポート
 - IaaS(主にAWS)で利用している既存の鍵をYubiKeyにImport
 - PagentをPC起動時に、YubiKeyにインポートした秘密鍵(CAPI)の設定を自動で読み込むように設定

#環境
####YubiKey
 + [YubiKey 5 NFC](https://www.yubico.com/jp/product/yubikey-5-nfc/)

####OS
 + Windows 10
 + RasberryPi (Raspberrypi 5.10.17-v7)

####Software
 + YubiKey Manager (Win)
 + yubico-piv-tool (RasberryPi)
 + PuTTy CAC
 + Pageant
 + PuTTygen

#参考リンク
 - [YubiKey Manager](https://www.yubico.com/support/download/yubikey-manager/)
 - [yubico-piv-tool reference (developers.yubico.com)](https://developers.yubico.com/yubico-piv-tool/)
 - [PuTTy CAC](https://github.com/NoMoreFood/putty-cac/releases)
 - [SSHの秘密鍵をYubiKeyで管理 Windows編(YubiOn)] (https://www.yubion.com/post/ssh%E3%81%AE%E7%A7%98%E5%AF%86%E9%8D%B5%E3%82%92yubikey%E3%81%A7%E7%AE%A1%E7%90%86-windows%E7%B7%A8)

---
#1.YubiKeyの初期設定
今回、YubiKeyはWindows 10にインストールした***YubiKey Manager***と、RaspberryPi OSにインストールした***yubico-piv-tool***を使って設定や鍵管理をしています。

##YubiKey Managerを使った初期パスワードの変更
YubiKey Managerは、YubiKeyの鍵の保管状況の確認や、各種パスワード設定が行えるツールです。

YubiKeyに鍵のImportなどを行うには***PIN***、***PUK***、***Management Key***という３つのパスワードが必要となります。出荷時にデフォルトのパスワードは設定されていますが、そのままではセキュリティ上問題なので、YubiKey Managerを使って、この初期パスワードを変更します。

##Windows版 YubiKey Managerのインストール##
yubico社の公式HPから、[Download](https://www.yubico.com/support/download/)します。
![YubiKeyManager.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245439/b0216688-7f89-9bb6-245d-c626aa80d324.png)

Windows 10にインストールするのでx64版を選択します。
![YubiKeyManagerx64.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245439/4c27aa1a-82eb-9190-4948-035c04bfb863.png)

ダウンロードした実行ファイルを、管理者権限で実行します。
![x64exe.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245439/78a85a51-3181-bf56-c002-ed7cca370877.png)

インストール後に起動すると、こんな感じ。
![unplugged.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245439/5335bb3c-01d7-3a4d-0e9c-aa9bccfe6bf7.png)

YubiKeyをUSB接続すると、変更できるようになります。
![plugged.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245439/273e3e16-3909-cc9b-5f67-fdd3d5de9974.png)

Applications > PIV > PIN Management のConfigure PINsを選択します。
![PIV_PIN.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245439/7e60e97d-628c-d9c9-c994-7a9fa0ad992b.png)

3種類のパスワードを設定します。まずは、***PIN***これはSSH接続する時など、秘密鍵の内容を読むときに使います。
![ConfPIN.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245439/39f47d15-f7c3-1cec-0493-2b077c676b7c.png)

出荷時にはデフォルトのPINが設定されています。Current PINは、右側のUse defaultにチェックを入れると自動的に現在のパスワードが入力されます。New PINに6～8文字の数字を設定します。Confirm new PINは確認です。
![PIN.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245439/362befbe-1a66-a3ed-8f84-1a7c3a47edf2.png)

次に、PUKを設定します。これはPINを3回入力間違いをした際に、ロック解除するためのパスワードです。
![ConfPIN.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245439/39f47d15-f7c3-1cec-0493-2b077c676b7c.png)

入力内容は、PINとまったく同様です。
出荷時にはデフォルトのPUKが設定されています。Current PUKは、右側のUse defaultにチェックを入れると自動的に現在のパスワードが入力されます。New PUKに6～8文字の数字を設定します。Confirm new PUKは確認です。
![PUK.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245439/bd635e58-8aac-cf27-96fb-18dfe2eb9f0f.png)

最後に、Management Keyを設定します。YubiKeyに秘密鍵をインポートする際などに利用します。***yubico-piv-tool***のコマンドでも利用するので、作業が終わるまでテキストファイルなどにコピーしておくのがお勧めです。
![ConfPIN.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245439/39f47d15-f7c3-1cec-0493-2b077c676b7c.png)

Current Management Keyは、PINやPUKと同様に、Use defaultにチェックをいれればOKです。New Management Keyは長いためGenerateで生成するのがいいでしょう。Protect with PINはチェックなしにしておきます。
![ManagementKey.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245439/1f022165-45e1-5b99-ba4e-34348d6cdbf4.png)

以上で初期設定は完了です。

#2. YubiKeyにインポートする秘密鍵をpem形式に変換
YubiKeyにインポートする鍵は、OpenSSHで利用できるPEM形式でなくてはいけません。

PEM形式で保存している場合は、そのまま***yubico-piv-tool***を使うLinuxにSCP等でコピーしてください。

PuTTyなどで使うためにppk形式などで秘密鍵を保存していた場合は、PEM形式に変換が必要です。
WindowsならPuTTygenなどを使って変換可能ですが、PuTTygenのOpenSSH形式は新旧2種類あって、**新しい形式はインポートできないので注意**。

PuTTygenでppk形式の秘密鍵を開き、
PuTTygen > Conversions > Export OpenSSH Keyを選択します。
*すぐ下のExport OpenSSH Key(force new file format)を選択するとインポートできないので注意*
出力したら、RaspberryPiなどのLinuxにSCP等でコピーします。
![puttygenconv.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245439/7574aeb4-7fc8-e228-b1dd-d29d0549e7a1.png)

PuTTygenで出力した秘密鍵(sample.pem)を、SSHKeygenでフォーマットを整えます。(上書き保存されるので注意)
パスワードなしで保存したいので、-pオプションを付与。-mオプションでPEM形式を指定。-fオプションで出力ファイル名を指定。

```
ssh-keygen -p -f sample.pem -m pem
```

生成した秘密鍵を元に、公開鍵を生成します。

```
openssl rsa -in sample.pem -pubout > sample_pub.pem
```

#3. Raspberry Pi OSに、***yubico-piv-tool***のインストール
apt-get installするだけです。

```
apt-get install yubico-piv-tool
```

#4. YubiKeyに秘密鍵のインポート
YubiKeyには、利用用途の異なる4つのSlotが存在します(9a、9c、9d、9e)。
9eのCard Authenticationなどは日本では利用することはなく、SSHの認証に関しては***どのSlotでも使える***ので好きなスロットを使います。
なお、YubiKeyの中には上記4つ以外のSlotも存在し、古い秘密鍵が保管されますが認証には利用できません。

ここでは、Slot 9cに秘密鍵をインポートします。
YubiKeyをRaspberry PiのUSBポートに差してください。

注意
***-kオプションの後に、空白を入れずにManagement Keyの文字列を入力してください***。
気付かず、エラーになる罠があります。なぜ、こんな仕様に…。(´・ω・｀)

-sオプションでスロットを指定するので、異なるSlotにインポートする場合は書き換えてください。

```
yubico-piv-tool -a import-key -s 9c -i [秘密鍵のファイル名] -K PEM -k[Management Keyの文字列]

yubico-piv-tool -a import-key -s 9c -i sample.pem -K PEM -k012345678901234567890123456789012345678901234567
```


公開鍵を自己署名して、自己署名証明書を作ります。
-Sオプションで入力するCNの欄に入力した値が、YubiKeyを接続した際の証明書選択画面に表示されます。
コマンド実行時に、PINの入力を求められるので、YubiKey Managerで設定したPINを入力します。

```
yubico-piv-tool -a verify-pin -a selfsign-certificate -s 9a -S "/CN=[CNの内容]/OU=[OUの内容]/O=[Oの内容]/" -i [公開鍵のファイル名] -o [自己署名証明書のファイル名] --valid-days=[有効日数]

yubico-piv-tool -a verify-pin -a selfsign-certificate -s 9a -S "/CN=test.example.local/OU=admin/O=example.local/" -i sample_pub.pem -o sample_cert_9c.pem --valid-days=3650
```


下記のコマンドで、YubiKeyのSlotに自己署名証明書が入っていないことを確認します。

```
yubico-piv-tool -a status -s [Slot名]

yubico-piv-tool -a status -s 9c
```


自己署名証明書をYubiKeyにインポートします。

```
yubico-piv-tool -a import-certificate -s 9a -i [自己署名証明書のファイル名] -K PEM -k[Management Keyの文字列]

yubico-piv-tool -a import-certificate -s 9a -i sample_cert_9c.pem -K PEM -k012345678901234567890123456789012345678901234567
```


YubiKeyのSlotに自己署名証明書がインポートされたことを確認します。

```
yubico-piv-tool -a status -s [Slot名]

yubico-piv-tool -a status -s 9c

```

[実行結果サンプル]

```
# yubico-piv-tool -a status -s 9c
CHUID:	108421c84210c3eb34109f089a07e3c3eb34109f089ac84210c3eb34109f089a07e3710842108421c84210c3eb34109f089a07e8421c84210c3eb3
CCC:	No data available
Slot 9c:	
	Algorithm:	RSA2048
	Subject DN:	CN=test.example.local, OU=admin, O=example.local
	Issuer DN:	CN=test.example.local, OU=admin, O=example.local
	Fingerprint:	bb923eb65c1862ba4927e4925fb4b83f8701f9bd9bb923eb65c1862b923eb659
	Not Before:	Sep 18 10:55:39 2021 GMT
	Not After:	Sep 17 10:55:39 2026 GMT
PIN tries left:	3
```

以上でYubiKey側の準備は完了です。

#5. PuTTy CAC + Pageantのセットアップ
Windows 10に戻って、SSH接続用のクライアントを構成します。
通常のPuTTyでは、YubiKeyにインストールした秘密鍵を使って接続することができません。
代わりに、[PuTTy CAC](https://github.com/NoMoreFood/putty-cac/releases)を利用します。

[PuTTy CAC](https://github.com/NoMoreFood/putty-cac/releases)から、x64版のMSI Installersをダウンロードして、インストールしてください。Pageantもインストールされます。
![PuttyCAC.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245439/9dfbb05a-e93e-fcf0-c13b-e8e429426110.png)


##Pageantの設定
YubiKeyをRaspberry Piから、Windowsに差し替えます。

スタートからPageantを起動し、タスクバーのPageantアイコンをダブルクリックします。
![pageant.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245439/81de8f1e-8dc4-b99d-db14-36917b665967.png)

Add CAPI Certを押します。
![addcapicert.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245439/4a1c1afe-e6ea-18a7-a58f-29ae5c035bf3.png)

Windowsの証明書選択画面が表示されるので、「その他」を押します。
![cert_select.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245439/aa71aab0-522e-7978-066f-db20a65715a4.png)

YubiKeyに含まれる証明書の情報が表示されるので、インポートした証明書を選択します。
![cert_selected.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245439/05b8a48d-9d33-babc-ba26-d5f5e46f9da3.png)

Pageantに証明書の登録が完了しました。
![Pagent_added.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245439/91284911-e1b5-e7a8-f4fd-c695b8f9e324.png)


##サーバーへSSH接続を行う(Tera Term + Pageantの場合)
Pageantが起動している状態で、Tera Termを起動します。
※PuTTy CACでも接続可能ですが、私の好みでTera Termを使います。
![teraterm.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245439/d7a282f2-3d47-326a-9c57-7a018f4b67d1.png)

ホストに接続先のFQDN or IPアドレスを入力します。
![teraterm_ssh.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245439/189fde35-5912-52a3-4624-852b7ecf9b29.png)

ユーザー名を入力し、「Pageantを使う」を選択します。
![putty_user.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245439/7b5301fc-0304-37b9-7d92-02964c109383.png)

PINの入力ポップアップが出るので、YubiKey Managerで設定したPINを設定します。
![enterPIN.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245439/22cd1826-904e-1f61-507b-46a55e0e649e.png)

接続先サーバーにつながります。


##サーバーへSSH接続を行う(PuTTy CAC + Pageantの場合)
Pageantが起動している状態で、PuTTy CACを起動します。
![putty.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245439/ea550c48-8658-f1ee-1a92-cd1b07d1855c.png)

Host Nameに接続先のFQDN or IPアドレスを入力し、Openを押します。
![putty_cac_ssh.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245439/21b7ff0e-47d8-b7fc-e3d3-7c15dfe77501.png)

Login as:というプロンプトが表示されるので、ユーザー名を入力します。
![putty_cac_loginas.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245439/738d0655-628c-dc9a-3fc5-76e1e8cecc10.png)

PINの入力ポップアップが出るので、YubiKey Managerで設定したPINを設定します。
![enterPIN.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245439/22cd1826-904e-1f61-507b-46a55e0e649e.png)

接続先サーバーにつながります。


##サーバーへSSH接続を行う(Pageantを使わずに、PuTTy CACだけでSSHする場合)
PuTTy CACを起動します。
![putty.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245439/ea550c48-8658-f1ee-1a92-cd1b07d1855c.png)

Host Nameに接続先のFQDN or IPアドレスを入力します。
![putty_cac_ssh.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245439/21b7ff0e-47d8-b7fc-e3d3-7c15dfe77501.png)

左側のCategoryから Connection > SSH > Certificate を展開し、「Set CAPI Cert...」を押します。
![putty_cac_ssh2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245439/46713a91-54a4-b115-a3b7-2a07ae209e0a.png)

Windowsの証明書選択画面が表示されるので、「その他」を押します。
![cert_select.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245439/aa71aab0-522e-7978-066f-db20a65715a4.png)

YubiKeyに含まれる証明書の情報が表示されるので、インポートした証明書を選択します。
![cert_selected.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245439/05b8a48d-9d33-babc-ba26-d5f5e46f9da3.png)

Openを押します。
![putty_cac_ssh3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245439/b4296257-c4e5-dbf8-9586-94265b92daf4.png)

Login as:というプロンプトが表示されるので、ユーザー名を入力します。
![putty_cac_loginas.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245439/738d0655-628c-dc9a-3fc5-76e1e8cecc10.png)

PINの入力ポップアップが出るので、YubiKey Managerで設定したPINを設定します。
![enterPIN.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245439/22cd1826-904e-1f61-507b-46a55e0e649e.png)

接続先サーバーにつながります。

#Pageant起動時に、CAPIなどの証明書を読み込む方法(2021/9/20追記)
Pageantを起動時に自動実行させて、証明書を読み込む設定を入れる方法は、下記記事を参照ください。
[[Win] Pageantを自動起動させて、あらかじめCAPIを読み込む設定を入れたい](https://qiita.com/ssgw39/items/200fda4b0cd3e8eef530)

以上