Как использовать аппаратный ключ для аутентификации по SSH? Для этого существует стандарт FIDO2, который позволяет использовать внешнее устройство. В этой статье как расскажу о том, как настроить вход с использованием аппаратного ключа YubiKey на macOS.

Весь процесс проделывал с:

  • YubiKey 5C NFC;
  • macOS 14.5 Sonoma.

Однако во многом инструкция подойдёт и для других систем, специфичные шаги я далее отмечу.

Подготовка

Для начала нужно убедиться, что установленный OpenSSH версии не ниже 8.3:

ssh -V

Если ниже, то обновитесь доступным способом, например, через brew.

macOS

Однако даже если версия SSH у вас корректная, скорее всего при выполнении дальнейших шагов вы столкнётесь с ошибкой:

Key enrollment failed: unknown or unsupported key type

Связано это с тем, что встроенный OpenSSH в macOS по умолчанию не поддерживает sk ключи. Но это легко исправить!

Есть GitHub Issue, в котором прекрасный человек под ником MichaelRoosz собрал все необходимые библиотеки в виде brew пакета, и на этапе подготовке давайте сразу установим этот пакет:

brew install michaelroosz/ssh/libsk-libfido2-install

После установки остаётся только прописать переменную окружения SSH_SK_PROVIDER и SSH_ASKPASS в вашем ~/.zshrc или ~/.bash_profile:

export SSH_SK_PROVIDER=/usr/local/lib/libsk-libfido2.dylib
export SSH_ASKPASS=/opt/homebrew/bin/ssh-askpass

И мы готовы к самому главному: генерации ключей.

Генерация

Поскольку перед нами стоит задача сгенерировать FIDO2 ключ, дальнейший путь разделяется на две дороги: нужно решить генерировать резидентский или нерезидентский ключ. Чем они отличаются?

Нерезидентский FIDO2 ключ

Когда конечная сторона (приложение или веб-сайт) хочет аутентифицировать вас, оно отправляет обязательный Credential ID. Это некая зашифрованная информация, которую расшифровать может ли ваш аппаратный ключ.

Сам процесс происходит за счёт использования уникального мастер-ключа. Обратите внимание, что это именно мастер-ключ: он один для всего аппаратного ключа, а вторую часть "формулы" – Credential ID, обязано предоставить приложение. Но при этом ни один из ваших аккаунтов не хранится в YubiKey, поэтому место нерезидентские ключи не расходуют, и их количество неограниченно.

Резидентский FIDO2 ключ

Резидентские или обнаруживаемые ключи, напротив, занимают слот на вашем аппаратном ключе. Их количество может разниться в зависимости от модели: на некоторых 8 слотов, на YubiKey 5 от 25 до 32, а на некоторых слотов нет совсем, а значит резидентский ключ сгенерировать невозможно.

В данном случае приложению не нужно предоставлять Credential ID: вся необходимая информация формируется на аппаратном ключе в момент добавления аккаунта. Если аккаунтов несколько, то браузер предложит выбрать конкретный. И далее уже сам ключ "расскажет" конечной стороне Credential ID и необходимую информацию для аутентификации.

Также сама по себе работа с резидентскими FIDO2 ключами отличаются из-за разных версий стандарта CTAP. На данный момент существуют версии 2.0, 2.1PRE и 2.1. И лишь 2.1PRE и 2.1 дают возможность вам удалить (освободить слот) резидентский ключ с устройства без сброса всего хранилища. Было бы неприятно добавить 25 ключей, и ради удаления одного сбрасывать все, м?

Так что выбрать, что безопаснее?

Обе опции являются безопасными. Да, в случае резидентского ключа вообще все чувствительные данные хранятся на аппаратном ключе, а у нерезидентского Credential ID есть у приложения. Однако нельзя сказать, что последнее плохо: Credential ID шифруется с AES128, а это довольно надёжный стандарт.

Однако если у вас очень много аккаунтов (больше или сравнительно с количеством слотов), то с обывательской точки зрения лучше выбрать опцию с неограниченными не-резидентскими ключами.

Команды

Для генерации не-резидентского ключа запустите:

ssh-keygen -t ed25519-sk

А для генерации резидентского:

ssh-keygen -t ed25519-sk -O resident -O application=ssh:my-hostname -O verify-required

Вместо ssh:my-hostname можете ввести любой текст, и далее он будет отображаться в Yubico Authenticator (или другом менеджере вашего аппаратного ключа в списке FIDO2):

Список FIDO2 ключей в Yubico Authenticator

И, кстати, да, генерация происходит привычным ssh-keygen. Если вы не пропустили шаг с подготовкой для macOS, то сейчас утилита должна попросить ввести пин-код и коснуться ключа. А по итогу появится id_ed25519_sk SSH ключ.

Публичную часть необходимо выгрузить на сервер:

ssh-copy-id -i ~/.ssh/id_ed25519_sk user@remote

После чего вы можете убедиться, что всё работает:

ssh -i ~/.ssh/id_ed25519_sk -o 'IdentitiesOnly yes' user@remote

Победа 🙂

Ссылки

Обязательно смотрите сам ролик про мою попытку безопасно работать с SSH: Как использовать SSH ПРАВИЛЬНО | YubiKey, FIDO2, PIV и правила использования SSH ключей.

И огромное количество информации я узнал благодаря статьям других авторов:

  1. Discoverable vs non-discoverable credentials в документации YubiKey
  2. How passkeys work в документации YubiKey
  3. ssh authentication via Yubikeys
  4. How Hype Will Turn Your Security Key Into Junk про разницу резидентских и не-резидентских ключей
  5. Тот самый Github Issue с решением для macOS и кучей полезной информации