SSH, PGP, TOTP в Yubikey 5

от автора

Что такое 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 для личных и рабочих целей, особенно в формате рабочий/домашний компьютер — пользуюсь и радуюсь 🙂


ссылка на оригинал статьи https://habr.com/ru/articles/574760/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *