Что такое Yubikey

Это аппаратный ключ безопасности, который поддерживает протокол универсальной двухфакторной аутентификации, одноразовые пароли и асимметричное шифрование. Если вы добавите его, допустим, в аккаунт на Гитхабе, то для входа в свой аккаунт, понадобится ввести логин/пароль и коснуться кнопки юбикей.

Год назад я приобрел Yubikey, чтобы использовать его в качестве второго фактора для аккаунтов Google, Github и других, которые работают с U2F. Однако я для себя выяснил, что Yubikey обладает куда более расширенным функционалом. Большая часть из нижеописанных действий  актуальна для работы и без Yubikey, однако преимущество в портативности будет потеряно.

Все действия описаны для Yubikey 5 и Ubuntu 21.04.

SSH-ключи

Многие знакомы с такой простой операцией, как подключение по SSH. У нас в TOT Systems имеется собственный менеджер паролей, и чтобы подключиться к удаленной машине, нужно зайти в него, скопировать логин, адрес и пароль.

Проблема паролей в том, что их можно подобрать, поэтому для авторизации по SSH часто используют RSA-ключи. Ключ состоит из двух частей - открытой и закрытой. Открытая часть должна быть на удалённой машине, а закрытая часть у пользователя в надёжном месте, т.е. приватный ключ никому показывать нельзя. Кто-то считает надежным местом облако или флешку - места, из которых теоретически можно достать этот самый ключ. Преимущество Yubikey в том, что приватный ключ из него извлечь не получится - даже пользователь его не знает.

Для работы нам понадобятся OpenSSH версии 8.2 и библиотека libfido2. Вместо привычного RSA-файла с приватным ключом давайте создадим ключ прямо на Yubikey с алгоритмом Ed25519.

Вставляем Yubikey в USB-порт и вводим команду с опцией resident, которая означает, что приватный ключ всегда будет храниться на Yubikey, а непосредственно в компьютере находится резидентный ключ, который без аппаратного ключа бесполезен:

 $ ssh-keygen -t ed25519-sk -O resident

user@pc:~$ ssh-keygen -t ed25519-sk -O resident 
Generating public/private ed25519-sk key pair.
You may need to touch your authenticator to authorize key generation.
Enter PIN for authenticator: 
Enter file in which to save the key (/home/user/.ssh/id_ed25519_sk): 
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /home/user/.ssh/id_ed25519_sk
Your public key has been saved in /home/user/.ssh/id_ed25519_sk.pub
The key fingerprint is:
SHA256:ztpJ8rTSlo07BQ0LyL6hI2X9/CE9fTdy0EQZhAnxc74 user@pc
The key's randomart image is:
+[ED25519-SK 256]-+
|   . .    oo =+o |
|    o . .  .o o  |
|   o   . +  oo.  |
|  o +   o . .+.  |
| o . = .So   ..  |
|. o . +o+ o o +. |
| . .  .+=B . +E. |
|      .BBo.      |
|      .o*o       |
+----[SHA256]-----+

Сначала нас попросят ввести пин-код от Yubikey. Если до этого вы не настраивали  свой юбикей, то User PIN по-умолчанию - 123456, а Admin PIN - 12345678. 

После ввода User PIN кнопка юбикей начнет мигать - нажимаем на неё. Выбираем место для сохранения ключей (предлагаю не менять директорию). Далее 2 раза вводим фразу-пароль для этого ключа.

В директории ~/.ssh появятся два файла: id_ed25519_sk.pub, который является обычным публичным ключом, и id_ed25519_sk, который является резидентным ключом и ссылается на приватный ключ в Yubikey.

Теперь добавим публичный ключ на SSH-сервер, к которому мы хотим подключиться. Для этого заходим на сервер как обычно с помощью пароля, переходим в папку ~/.ssh и находим в ней файл authorized_keys, а если его нет, то создаём. В этот файлик копируем содержимое нашего публичного ключа. Пробуем авторизоваться:

user@pc:~$ ssh user@192.168.0.12
Enter passphrase for key '/home/user/.ssh/id_ed25519_sk': 
Confirm user presence for key ED25519-SK SHA256:ztpJ8rTSlo07BQ0LyL6hI2X9/CE9fTdy0EQZhAnxc74
Welcome to Ubuntu 21.04 (GNU/Linux 5.11.0-25-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

0 updates can be applied immediately.

*** System restart required ***
Last login: Sat Jul 24 20:12:35 2021 from 192.168.0.47

Нас попросят ввести фразу-пароль от ключа, а затем нажать на кнопку Yubikey - успешно авторизуемся. При этом возможность авторизоваться по паролю никуда не пропала.

Если предварительно вынуть юбикей из USB-порта и попробовать авторизоваться, то после ввода парольной фразы от ключа у нас будет ошибка и нам будет предложено ввести пароль от сервера.

Сгенерировать ключи и хранить их на компьютере можно и без Yubikey, но в таком случае возникает потребность в переносе приватного ключа между компьютерами, на которых необходим доступ к серверу.  Преимущество Yubikey в том, что ключи всегда хранятся на нём, и при работе на другом компьютере можно легко получить резидентный и публичный ключи.

К примеру, импортируем ключи с юбикея на новый компьютер. Запускаем терминал в папке ~/.ssh:

$ ssh-keygen -K

Вводим пин-код, парольную фразу и получаем два файла: id_ed25519_sk_rk (резидентный ключ) и id_ed25519_sk_rk.pub (публичный ключ). Переименовываем id_ed25519_sk_rk в id_ed25519_sk. Успешно авторизуемся на новом компьютере.

SSH-ключ и U2F на примере Github

С помощью SSH-ключа можно клонировать репозиторий на гитхабе. Для этого добавляем публичный ключ в аккаунт на гитхабе. Теперь попробуем клонировать репозиторий по SSH:

user@pc:~/Документы$ git clone git@github.com:oleguka/Store.git
Клонирование в «Store»…
Enter passphrase for key '/home/user/.ssh/id_ed25519_sk': 
Confirm user presence for key ED25519-SK SHA256:ztpJ8rTSlo07BQ0LyL6hI2X9/CE9fTdy0EQZhAnxc74
remote: Enumerating objects: 30, done.
remote: Counting objects: 100% (30/30), done.
remote: Compressing objects: 100% (19/19), done.
remote: Total 30 (delta 0), reused 30 (delta 0), pack-reused 0
Получение объектов: 100% (30/30), 55.69 KiB | 670.00 KiB/s, готово.

Нас попросят ввести парольную фразу, а также коснуться кнопки юбикея. Вуаля - репозиторий клонирован. Теперь можно проверить, будет ли клонирован репозиторий без юбикея. Вытаскиваем его из USB-порта и попытаемся клонировать другую репу.

user@pc:~/Документы$ git clone git@github.com:oleguka/Cookie.git
Клонирование в «Cookie»…
Enter passphrase for key '/home/user/.ssh/id_ed25519_sk': 
Confirm user presence for key ED25519-SK SHA256:ztpJ8rTSlo07BQ0LyL6hI2X9/CE9fTdy0EQZhAnxc74
sign_and_send_pubkey: signing failed for ED25519-SK "/home/user/.ssh/id_ed25519_sk": invalid format
git@github.com: Permission denied (publickey).
fatal: Не удалось прочитать из внешнего репозитория.

Удостоверьтесь, что у вас есть необходимые права доступа
и репозиторий существует.

Клонировать репу не получается.

Поддержка U2F для SSH-ключей на данный момент реализована только в гитхабе. Если у вас используется gitlab, то использовать ключ с юбикея, к сожалению, не получится.

GPG

Теперь поговорим про GPG - программу с ассиметричным шифрованием. С её помощью можно шифровать, подписывать данные, а также авторизовываться по SSH на серверах. Давайте подпишем коммит с помощью gpg.

Для работы с Yubikey Нужно установить scdaemon:

$ sudo apt install scdaemon

При выводе списка ключей gpg по умолчанию показывает ключи без id - только их отпечаток. Предлагаю это исправить, поскольку для дальнейших действий удобно использовать именно id ключей. Для этого в папке ~/.gnupg создаем конфиг gpg.conf, а в нём пишем одну строчку - keyid-format long.

Перед созданием RSA-ключа и сабключей поменяем их размер на 4096 бит.

Для этого перейдём в меню смарт-карты.

user@pc:~$ gpg --card-edit 

Reader ...........: 1050:0407:X:0
Application ID ...: D2760001240103040006134534820000
Application type .: OpenPGP
Version ..........: 3.4
Manufacturer .....: Yubico
Serial number ....: 13453482
Name of cardholder: Oleg Tolstykh
Language prefs ...: ru
Salutation .......: Mr.
URL of public key : https://github.com/otolstykh.gpg
Login data .......: olegulka
Signature PIN ....: не требуется
Key attributes ...: rsa2048 rsa2048 rsa2048
Max. PIN lengths .: 127 127 127
PIN retry counter : 3 0 3
Signature counter : 5
KDF setting ......: off
Signature key ....: [none]
Encryption key....: [none]
Authentication key: [none]
General key info..: [none]

Появилась основная информация о нашей карте. Видим, что длина ключа 2048 - переключаемся в админ-режим:

gpg/card> admin

и отредактируем длину ключа на 4096:

gpg/card> key-attr 
Изменение атрибутов ключа на карте: Ключа для подписи
Выберите тип ключа:
   (1) RSA
   (2) ECC
Ваш выбор? 1
Какой размер ключа Вам необходим? (2048) 4096
Изменение атрибутов ключа на карте: Ключа для шифрования
Выберите тип ключа:
   (1) RSA
   (2) ECC
Ваш выбор? 1
Какой размер ключа Вам необходим? (2048) 4096
Изменение атрибутов ключа на карте: Ключа для удостоверения личности
Выберите тип ключа:
   (1) RSA
   (2) ECC
Ваш выбор? 1
Какой размер ключа Вам необходим? (2048) 4096

Теперь перейдём к созданию ключей. В самом начале у нас спросят, делать ли резервную копию ключа шифрования. Также спросят срок жизни ключей. Отредактировать этот срок можно в любой момент.

gpg/card> generate 
Сделать вне карты архивную копию ключа шифрования? (Y/n) n

Выберите срок действия ключа.
         0 = не ограничен
      <n>  = срок действия ключа - n дней
      <n>w = срок действия ключа - n недель
      <n>m = срок действия ключа - n месяцев
      <n>y = срок действия ключа - n лет
Срок действия ключа? (0) 0
Срок действия ключа не ограничен
Все верно? (y/N) y

GnuPG должен составить идентификатор пользователя для идентификации ключа.

Ваше полное имя: Oleg Tolstykh
Адрес электронной почты: otolstykh@yandex.ru
Примечание: Yubikey
Вы выбрали следующий идентификатор пользователя:
    "Oleg Tolstykh (Yubikey) <otolstykh@yandex.ru>"

Сменить (N)Имя, (C)Примечание, (E)Адрес; (O)Принять/(Q)Выход? O
gpg: ключ 60D70CA6AFBAB10F помечен как абсолютно доверенный
gpg: создан каталог '/home/user/.gnupg/openpgp-revocs.d'
gpg: сертификат отзыва записан в '/home/user/.gnupg/openpgp-revocs.d/306836E54FE0FF47B9277BDB60D70CA6AFBAB10F.rev'.
открытый и секретный ключи созданы и подписаны.

Проверяем, что ключ сгенерировался  и отображается на карте:

gpg/card> list

Reader ...........: 1050:0407:X:0
Application ID ...: D2760001240103040006134534820000
Application type .: OpenPGP
Version ..........: 3.4
Manufacturer .....: Yubico
Serial number ....: 13453482
Name of cardholder: Oleg Tolstykh
Language prefs ...: ru
Salutation .......: Mr.
URL of public key : https://github.com/otolstykh.gpg
Login data .......: olegulka
Signature PIN ....: не требуется
Key attributes ...: rsa4096 rsa4096 rsa4096
Max. PIN lengths .: 127 127 127
PIN retry counter : 3 0 3
Signature counter : 4
KDF setting ......: off
Signature key ....: 3068 36E5 4FE0 FF47 B927  7BDB 60D7 0CA6 AFBA B10F
      created ....: 2021-07-29 07:27:33
Encryption key....: E1CB FF3A 8F81 8B63 59A7  068C F92E 2F31 6078 5D40
      created ....: 2021-07-29 07:27:33
Authentication key: 8493 6F5D 23D0 8D09 D918  BEE6 9C3A 3873 BA8A 4CC1
      created ....: 2021-07-29 07:27:33
General key info..: 
pub  rsa4096/60D70CA6AFBAB10F 2021-07-29 Oleg Tolstykh (Yubikey) <otolstykh@yandex.ru>
sec>  rsa4096/60D70CA6AFBAB10F  создан: 2021-07-29  годен до: никогда     
                                номер карты: 0006 13453482
ssb>  rsa4096/9C3A3873BA8A4CC1  создан: 2021-07-29  годен до: никогда     
                                номер карты: 0006 13453482
ssb>  rsa4096/F92E2F3160785D40  создан: 2021-07-29  годен до: никогда     
                                номер карты: 0006 13453482

Выводим содержимое публичного ключа в терминал:

user@pc:~$ gpg --armor --export 60D70CA6AFBAB10F

Или экспортируем публичный ключ в файл, а затем добавляем его в свой аккаунт в гитлабе:

user@pc:~$ gpg --output .gnupg/yubikey.asc --armor --export

Теперь создадим глобальный конфиг файл ~/.gitconfig с содержимым:

[user]
	name = otolstykh
	email = otolstykh@yandex.ru
	signingkey = 60D70CA6AFBAB10F
[commit]
  gpgsign = true

Или если у вас IDEA версии 2021.2 и выше, то вы можете прямо в её настройках выбрать ключ для подписи коммитов - Settings | Version Control | Git | Configure GPG Key

После этого ваши коммиты будут подписаны:

Допустим, мы хотим воспользоваться нашими ключами на новом компьютере. Для этого на карте нужно указать url публичного ключа. Для этого переходим к редактированию карты и в админ-режиме редактируем url:

gpg/card> url
URL для получения открытого ключа: https://github.com/otolstykh.gpg

Для гитхаба url нашего ключа выглядит так. Для гитлаба аналогично. Вы можете хранить публичный ключ на любом сервере публичных ключей.

Теперь на новом компьютере вводим команду fetch

gpg/card> fetch 
gpg: запрос ключа из 'https://github.com/otolstykh.gpg'
gpg: ключ 60D70CA6AFBAB10F: импортирован открытый ключ "Oleg Tolstykh (Yubikey) <otolstykh@yandex.ru>"
gpg: Всего обработано: 1
gpg:               импортировано: 1

Далее повысим уровень доверия к ключу командой trust:

user@home:~$ gpg --edit-key 60D70CA6AFBAB10F

gpg> trust 
sec  rsa4096/60D70CA6AFBAB10F
     создан: 2021-07-29  годен до: никогда       назначение: SC  
     номер карты: 0006 13453482
     доверие: неизвестно достоверность: неизвестно
ssb  rsa4096/9C3A3873BA8A4CC1
     создан: 2021-07-29  годен до: никогда       назначение: A   
     номер карты: 0006 13453482
ssb  rsa4096/F92E2F3160785D40
     создан: 2021-07-29  годен до: никогда       назначение: E   
     номер карты: 0006 13453482
[ неизвестно ] (1). Oleg Tolstykh (Yubikey) <otolstykh@yandex.ru>

Укажите, насколько Вы доверяете данному пользователю в вопросах проверки
достоверности ключей других пользователей (проверяет паспорт,
сверяет отпечатки ключей из разных источников и т.п.)

  1 = Не знаю или не буду отвечать
  2 = НЕ доверяю
  3 = Доверяю ограниченно
  4 = Полностью доверяю
  5 = Абсолютно доверяю
  m = вернуться в главное меню

Ваше решение? 5
Вы действительно хотите сделать этот ключ абсолютно доверенным? (y/N) y

sec  rsa4096/60D70CA6AFBAB10F
     создан: 2021-07-29  годен до: никогда       назначение: SC  
     номер карты: 0006 13453482
     доверие: абсолютное достоверность: неизвестно
ssb  rsa4096/9C3A3873BA8A4CC1
     создан: 2021-07-29  годен до: никогда       назначение: A   
     номер карты: 0006 13453482
ssb  rsa4096/F92E2F3160785D40
     создан: 2021-07-29  годен до: никогда       назначение: E   
     номер карты: 0006 13453482
[ неизвестно ] (1). Oleg Tolstykh (Yubikey) <otolstykh@yandex.ru>
Учтите, что показанная достоверность ключа может быть неверной,
пока Вы не перезапустите программу.

Всё, теперь мы можем подписывать коммиты, шифровать файлы с помощью одного ключа, который всегда хранится на Yubikey, и если юбикей не вставлен в порт компьютера, то сделать это нельзя.

TOTP

И последнее, о чем я хочу рассказать - это использование Yubikey для генерации одноразовых кодов, причём коды будут храниться, разумеется, на Yubikey. В этом случае не нужно думать о бэкапе кодов в приложении при смене смартфона или переустановке системы. Однако нужно будет пользоваться приложением от Yubikey, которые есть для iOS/Android. У меня версия Yubikey c обычным USB-портом и NFC. Чтобы добавить код или считать список всех кодов, достаточно поднести юбикей к NFC считывателю смартфона. Таким образом я добавил все сервисы, которыми пользуюсь и в которых нет поддержки U2F, однако добавить второй фактор в Яндексе у меня не получилось, так как они используют Двухфакторную аутентификацию, которой удобно пользоваться (на самом деле не так удобно), и коды для Яндекса возможно генерировать только в их приложении.

В заключение. Лично мне безумно удобно использовать Yubikey для личных и рабочих целей, особенно в формате рабочий/домашний компьютер - пользуюсь и радуюсь :)

Комментарии (27)


  1. asp13
    26.08.2021 13:44
    +1

    Подскажите, пожалуйста, каков план ваших действий если
    1) Ключ был безвозвратно утерян или физически повреждён

    2) Вы подъезжая к дому с планами плодотворно поработать сообразили, что забыли вытащить ключ из рабочей машины

    3) Вы планируете пользоваться ноутбуком на коленях/"на бегу", а ключ так неудобно торчит из USB-порта, что есть опасения его повредить?


    1. farcaller
      26.08.2021 13:47
      +1

      1, 2 — несколько ключей. Для 1 хорошо подходит "ключ в сейфе", для 2 — ключ на общей связке ключей


    1. olegulka Автор
      26.08.2021 14:03

      1) Для такого обычно рекомендуется использовать резервный Yubikey - тогда в аккаунт можно зайти с него и удалить потерянный. Или воспользоваться резервными кодами доступа - их выдает любой сервис, где вы подключаете второй фактор. SSH и PGP ключи удаляются там, где они используются. Если в качестве второго фактора используются TOTP коды, то в аккаунт также можно войти по резервным кодам.

      2) Такого не случалось - Yubikey всегда лежит на столе и забыть его также сложно как телефон, или ключи от квартиры.

      3) В таком случае можно взять nano-версии Yubikey - они стоят чуть дороже и в них нет NFC.


      1. asp13
        26.08.2021 15:47

        Спасибо!


      1. rstepanov
        26.08.2021 19:06

        Type-C есть? На маке работает?


        1. olegulka Автор
          26.08.2021 19:16

          YubiKey 5C Nano - на маке работает


          1. vikarti
            26.08.2021 20:11

            А в контексте статьи (ssh/gpg) это точно работает? (так то ключики работают с тем же Bitwarden и Chrome)
            Потому что


            vikarti@IRUNA ~ % ssh-keygen -t ed25519-sk -O resident
            Unsupported certificate option "resident"
            vikarti@IRUNA ~ % sw_vers
            ProductName: macOS
            ProductVersion: 11.5.1
            BuildVersion: 20G80


            1. olegulka Автор
              29.08.2021 20:34

              С gpg должно работать, ssh - не знаю, мака под рукой нет проверить.


            1. Tihon_V
              31.08.2021 01:47
              +1

              В macOS достаточно "архаичный" ssh. Если обновить – все работает.

              brew install openssh


  1. farcaller
    26.08.2021 13:49
    +1

    Мне больше понравилось работать с ssh через gpg. Немного упоротее настройка, но работает даже там где поддержки новомодного ed25519_sk нет. При этом сохраняется поддержка физически тапнуть по ключу для логина.


  1. barlone
    26.08.2021 14:04

    Спасибо за статью. А опыт работы под Windows с Yubikey имеется? Будем благодарны если поделитесь. Тоже есть ключ, но разобрался не со всем, что он может.


    1. Graphite
      26.08.2021 14:07

      Под Windows я настраивал пару лет назад SSH через PGP - настройка слегка упоротая, но потом работает нормально.


  1. romxx
    26.08.2021 16:35
    +1

    1. AotD
      26.08.2021 17:08
      +1

      Спокойно покупается в softline, например


      1. romxx
        26.08.2021 17:30
        -1

        "спокойно" оно по разному покупается. Но помнить, в какой мы компании для производителя находимся, все же стоит.


    1. Anatol_s
      26.08.2021 19:46

      Можно купить на GitHub с доставкой в СНГ.

      https://thegithubshop.com/collections/yubikeys


    1. GooG2e
      31.08.2021 14:49

      Им можно написать на почту и вышлют отдельно. Я так заказывал когда он только вышел. Отдельно платишь за ключ и доставку.


  1. overlapped
    26.08.2021 16:55

    • В РФ нет доставки

    • Есть подобное в РФ?


    1. AotD
      26.08.2021 17:10

      Один покупал в Softline, второй заказывал на Amazon вместе с другими штуками, они некоторые товары спокойно отправляют в Россию.


    1. olegulka Автор
      26.08.2021 19:18

      На амазоне можно заказать - доставка в РФ есть.


    1. cowax
      29.08.2021 21:30

      Да, есть!
      Купил тут:
      https://yubikey.ru/


  1. labyrinth
    27.08.2021 09:15

    Повторить подобное с JaCarta не думали?


    1. olegulka Автор
      27.08.2021 11:15

      Не увидел у них токенов с поддержкой SHH, GPG, TOTP


      1. labyrinth
        27.08.2021 11:59

        да, но что-то похожее на это и это


  1. nymitr
    29.08.2021 16:14

    Очень подробный guide по настройке и использованию YubiKey с GPG: YubiKey-Guide


  1. KGBmen
    29.08.2021 20:37

    В моей практике был проект внедрения Yubikey 5 как одного из компонентов мультифакторной аутентификации на ресурсах MS Azure. Пока что никаких нареканий на ключики нет.


  1. cowax
    29.08.2021 20:37

    Yubikey5NFC не получилось с SSH, подскажите пожалуйста, если знаете в чем ошибка?

    ssh-keygen -t ed25519-sk -O resident
    Generating public/private ed25519-sk key pair.
    You may need to touch your authenticator to authorize key generation.
    Enter PIN for authenticator:
    Key enrollment failed: invalid format