Plan 9とGo言語のブログ

主にPlan 9やGo言語の日々気づいたことを書きます。

FIDO U2Fセキュリティキーを使ってSSHする

今年の5月に、GitHubがFIDO U2Fセキュリティキーを利用したSSH接続に対応したので、手元にあったTitan Security Keyで試してみました。

Titan Security Keyを買ったときの話はこちら。

SSH鍵の生成

SSHでFIDO U2Fセキュリティキーを参照するためにはOpenSSH 8.2以上が必要です。Arch Linuxでは少なくともopenssllibfido2の2つが必要なのでpacmanでインストールします。

$ sudo pacman -S openssh libfido2
$ ssh -V
OpenSSH_8.6p1, OpenSSL 1.1.1k  25 Mar 2021

また、鍵ペアはecdsa-skまたはed25519-skで作っておく必要があります。セキュリティキーを接続した状態でssh-keygenを使って作成しましょう。YubiKeyなど、この時点でセキュリティキーへのタッチを要求される場合もあるそうですが、Titan Seciruty Keyではタッチは要求されず、パスフレーズを聞かれただけでした。

$ ssh-keygen -t ecdsa-sk -C user@example.org
Generating public/private ecdsa-sk key pair.
You may need to touch your authenticator to authorize key generation.
Enter file in which to save the key (/home/lufia/.ssh/id_ecdsa_sk): 
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /home/lufia/.ssh/id_ecdsa_sk
Your public key has been saved in /home/lufia/.ssh/id_ecdsa_sk.pub
SHA256:h7O7eF62nwJCHxnnelOX0QUlufa144r/gjOZWBWhmnM lufia@linux-pc
(snip)

ここで、セキュリティキーを接続せずにssh-keygenを実行すると、

Key enrollment failed: invalid format

というエラーで終了します。

ecdsa-skまたはed25519-sk(以下めんどうなのでecdsa-skだけを表記します)では、他のものと同様にid_ecdsa_skid_ecdsa_sk.pubの2つファイルを生成しますが、他のものと異なり秘密鍵はセキュリティキーに保存*1されていて、id_ecdsa_skファイルには、セキュリティキーへの参照などの盗まれても安全な情報だけが含まれるようです。id_ecdsa_skのフォーマットはデフォルトではRFC 4716 - The Secure Shell (SSH) Public Key File Formatです。

id_ecdsa_skファイルに保存されている具体的な情報については面倒なので追ってませんが、秘密鍵をセキュリティキーに要求する部分のコードはsshconnect2.c:1232-1270の辺りなので、ここでsshkey_is_sksshkey_typeするために必要な情報が含まれているのでしょう。興味があればload_identity_filesshkey_load_private_type辺りを読んでみてください。

SSH鍵を使う

ecdsa-sk鍵を用意できたら、GitHubのSettings → SSH and GPG keysに公開鍵(id_ecdsa_sk.pub)を登録します。ここはよくある手順なので省略。

登録が終わったら、以下のコマンドで確認してみましょう。

$ ssh -T -i id_ecdsa_sk git@github.com
Enter passphrase for key 'id_ecdsa_sk': ***
Confirm user presence for key ECDSA-SK SHA256:h7O7eF62nwJCHxnnelOX0QUlufa144r/gjOZWBWhmnM
User presence confirmed
Hi lufia! You've successfully authenticated, but GitHub does not provide shell access.

実行例だと分かりづらいですが、

Confirm user presence for key ECDSA-SK SHA256:h7O7eF62nwJCHxnnelOX0QUlufa144r/gjOZWBWhmnM

のところで止まるので、セキュリティキーにタッチすると先に進みます。セキュリティキーが接続されていない場合は、

sign_and_send_pubkey: signing failed for ECDSA-SK "id_ecdsa_sk": invalid format

というエラーで接続に失敗します。

感想

最近は、GitHubへのアクセスではアクセストークンを使っているし、SSHでリモートログインする機会もだいぶ減りましたが、とはいえたまに使うことはあるので、ファイルを盗まれても安全で、TOTPほど面倒でもないのはいいですね。ただ、セキュリティキーが手元にないときは何もできないので忘れないようにしましょう。

セキュリティキー便利なので使っていきたいんですが、意外と対応しているサービスは少ないですね*2AWS CLIでもFIDO U2Fセキュリティキーがサポートされたら嬉しいのですが、コンソールログインでは使えるけどCLIでは使えず、MFAデバイスは1つだけしか登録できない制約があるので、現状ではTOTPするしかないのが悲しい*3

*1:Titan Security Keyは複数の鍵を管理する機能を持っていないと思いますが

*2:Mackerelも対応していないけどそこは見なかったことに...

*3:Mackerelも1つしか登録できないけどこれも忘れてください...