К 2025 году сложился достаточно насыщенный вторичный рынок USB-ключей eToken. Встретить их по ценам от нуля до весьма символических можно как на просторах барахолок, так и из рук в руки, как штучно, так и коробками. В то же время eToken NG-OTP является гостем редким и весьма интересным, и применить его во благо хотелось бы.
Внимание! Действия, указанные в статье, могут привести к утрате данных с USB-ключа и к утрате доступа к серверу. Автор не несет ответственности за ошибочные действия других лиц, даже если вдохновил их на данные действия.
В данной статье речь пойдет об Aladdin eToken NG-OTP 72k (Java) с семисегментным ЖКИ, однако многие рассуждения полностью справедливы и для других разновидностей из этого семейства (в том числе без Java и с матричным ЖКИ) и частично справедливы для любых брелоков eToken. Поэтому если у вас фиолетовый eToken без дисплея, тоже милости прошу.
Упомянутый продукт является устаревшим, действующие сертификаты ФСТЭК на него отсутствуют, поэтому вопрос его применения для электронной подписи остается полностью за кадром. Сейчас брелок интересен тем, что является гибридным решением, и функции свои не утратил. Это не только 20 граммов USB-ключа, но и генератор одноразовых паролей. Формально он, как и все версии eToken со словом Java в названии, поддерживает и установку своих Java-апплетов, но ключи для установки мне неизвестны, поэтому в этот раз не попишем приложений, к великому сожалению.
Статья разделена на две относительно независимые половины: аутентификация на сервере с помощью USB-ключа и задействование второго фактора — одноразового пароля.
Аутентификация с помощью USB-ключа для удаленного управления сервером по SSH
Серверы зачастую расположены неудобно для непосредственного к ним доступа (в дата-центрах, а порой на антенных мачтах и в более экзотических местах типа подвалов и пещер), поэтому удаленное управление по SSH давно стало стандартом де-факто из-за удобства и безопасности.
Небезопасность парольного доступа широко известна, последовательно и методично освещена в многочисленных источниках (например, в справочных системах хостингов). В качестве альтернативы предлагается, как правило, аутентификация с помощью ключевой пары RSA, и это разумное решение, но тут-то случается подвох: закрытый ключ предлагается создать (PuTTYgen.exe) и хранить локально (даже без парольной защиты), а порой и вовсе генерировать на сервере (ssh-keygen) с последующим скачиванием для локального хранения.
Сильная же сторона RSA и более новых несимметричных алгоритмов как раз в том, чтобы закрытый ключ оставить в безопасной среде, а не заставлять его лежать на сервере или гулять по локальным хранилищам. Там-то, в безопасной среде eToken NG-OTP, мы и вырастим ключевую пару RSA сейчас.
На самом деле тема не нова, и тематическая статья на Хабре выходила много лет назад. Вот только ссылки в ней уже либо нерелевантны, либо 404-нулись за годы, а решения устарели и не работают, хотя в комментариях есть и полезная информация. Поэтому фактически попробуем почти то же самое, но с помощью ПО, которое на начало 2025 года доступно и в идеальном сценарии еще поддерживается разработчиками, чтобы на дольше хватило.
Для примера договоримся, что сервер под Ubuntu 24 (если Debian, CentOS, Fedora, то место хранения открытых ключей может не совпасть, но принципиально ничего не изменится), OpenSSH sshd работает, парольный доступ отключен, а аутентификация по ключам задействована. Такую конфигурацию зачастую дают хостеры при заказе через панель, а при самостоятельной установке это может потребовать дополнительной ручной работы, описание которой выходит за рамки статьи. Предположим, что закрытый ключ сейчас хранится локально и легкодоступен, тогда как после нижеописанных экзекуций он станет неизвлекаемым.
Для единообразия скриншотов также предположим, что управляющий клиент работает под 64-разрядной Windows 10, хотя инструменты не сильно придирчивы к версии ОС, а часть из них и вовсе кроссплатформенна.
Инструментарий
-
Putty CAC, или
саснаяверсия Putty с поддержкой смарт-карт (коей сабж и является). На момент написания статьи доступна версия 0.82 Update 1 с датой выхода 2 декабря 2024 года. Есть даже поддержка ARM и ARM64. -
XCA для управления процессом создания ключей. Инструмент кроссплатформенный. Для регулярного использования не требуется, после завершения настроечного этапа допустимо удалить. Доступна версия 2.8.0 от 13 октября 2024.
-
eToken PKI Client 5.1 для непосредственного доступа к USB-ключу. Зверь древний и неприятный тем, что остался лишь в неофициальных источниках либо у некоторых бывших дистрибьюторов. Было бы интересно заменить на что-то в духе OpenSC, но этот вопрос пока за кадром.
Связка из пунктов 1 и 2 достаточно перспективна и поддерживает не только eToken. Третий же пункт довольно специфичен. Установка инструментов ничем не примечательна, поэтому движемся сразу к использованию.
Брелок почти наверняка был в употреблении, поэтому его удобно заново инициализировать, чтобы удалить имеющиеся ключи и сертификаты, а заодно сбить забытый пароль. Сделать это без особого труда позволяет приложение eToken Properties (etProps.exe), которое ставится в составе клиентского набора (пункт 3 выше).
Детально процесс не описываю из-за его тривиальности. Достаточно запустить eToken Properties, перейти в Advanced View (шестеренка), выбрать устройство и нажать Initialize eToken. Далее интерактивный мастер направит в нужное русло.
Стоит отметить, что перед продолжением целесообразно зайти в Advanced. Галочки Load 2048-bit RSA key support и Load OTA support нужны. Заодно можно отказаться от кеширования (Private data caching mode) и разрешить задавать дополнительные пароли для ключевых пар (RSA key secondary authentication mode).
После ввода этих настроек можно двигаться по инструкциям мастера к завершению процесса.
Внимание! Ключ генератора одноразовых паролей тоже будет уничтожен при инициализации. Дисплей будет показывать «Err 14» и ничего более до ввода нового ключа. Это нормально.
С инициализацией на этом все, далее нужно создать что-нибудь полезное на борту. В этом поможет XCA.
При первом запуске XCA взаимодействие с USB-устройствами неактивно. Чтобы это исправить, требуются два неинтуитивных шага.
-
Создать базу данных. File → New DataBase, далее процесс тривиален. Серьезный пароль для этой базы задавать не имеет смысла, ничего существенного в ней не хранится, после завершения настройки она может быть удалена.
-
Зайти в настройки и добавить eToken.dll: File → Options, вкладка PKCS#11 Provider. Можно воспользоваться поиском, можно сразу нажать Add и выбрать файл C:WindowsSystem32eToken.dll, на том подготовительный этап завершен.
Далее для создания ключевой пары в главном окне XCA на вкладке Private Keys нужно нажать New Key, ввести любое удобное имя, в поле Keytype выбрать eToken, длину выставить 2048 бит (свыше 2048 брелок не умеет, а меньше нет смысла) и нажать Create.
Брелок попросит пароль, после чего задумается на непродолжительное время, мигая индикатором. В это время происходит создание ключевой пары RSA внутри eToken NG-OTP. Извлечение закрытого ключа не предусмотрено. Открытый ключ экспортировать необходимо, поскольку он потребуется в дальнейшем. В списке ключей выбираем только что созданную пару, нажимаем Export.
Настройки экспорта нехитрые, это путь к файлу и формат этого самого файла. Для дальнейшего применения рекомендую SSH2 public (*.pub), он открывается текстовым редактором и подходит для закидывания на сервер.
Содержимое файла Test.pub (а именно строку, начинающуюся с ssh-rsa AAAA) нужно дописать в /root/.ssh/authorized_keys на сервере.
Например,
nano /root/.ssh/authorized_keys
и вставить строку со свежим открытым ключом под существующими. Удалять старые открытые ключи сейчас преждевременно; лучше это сделать, когда аутентификация с помощью нового ключа будет проверена.
Далее ^O, ^X,
systemctl restart ssh
и сервер готов к тесту входа с помощью нового ключа.
Клиент еще не совсем готов. Нужно создать фиктивный самоподписанный сертификат, с помощью которого PuTTY CAC будет ссылаться на ключ. Это тоже несложно сделать с помощью XCA. Кнопка New Certificate на вкладке Certificates запустит инструмент создания сертификатов.
Из обязательных настроек здесь Internal Name и Private key (если ключей несколько). Остальное по умолчанию подходит. Можно заполнить пустые поля, но создание сертификата удастся и без этого.
Также на вкладке Extensions в поле Type стоит выбрать End Entity.
Далее OK, пароль и успех. Осталось подтвердить запись сертификата на eToken (и по пути снова ввести пароль).
Если имеется второй брелок, целесообразно повторить все шаги с ним, чтобы создать резервный ключ и спрятать его в собачьей конуре сейфе.
После этого XCA можно удалить вместе с созданной ранее базой. Все нужные элементы уже хранятся на USB-носителе.
Осталось слегка настроить PuTTY CAC.
После нажатия на кнопку Set PKCS Cert... нужно выбрать не сертификат, а все ту же библиотеку для доступа к eToken (по умолчанию C:WindowsSystem32eToken.dll).
Далее действительно предлагается выбор сертификата. Тут OK, если он единственный.
Сейчас стоит ткнуть кнопку Copy To Clipboard, чтобы в буфер обмена без лишних движений втянуть отпечаток сертификата.
Можно пробовать соединиться. Если проблем не возникло, то старые открытые ключи с сервера желательно удалить.
Осталось создать ярлык, чтобы не вводить путь к eToken.dll каждый раз, а для этого как раз удобно использовать содержимое буфера обмена, предварительно вставив его в любой Notepad++.
putty.exe root@127.0.0.1 -i PKCS:xxx<...>xxx=C:WindowsSystem32eToken.dll
Аутентификация с помощью USB-ключа eToken NG-OTP готова, осталось поднять генератор одноразовых паролей.
Настройка генератора одноразовых паролей
Особенность eToken NG-OTP, а именно встроенный генератор одноразовых паролей, настраивается чуть хитрее. Это HOTP на 6 цифр на основе HMAC-SHA1. Без ключа он показывает только «Err 14», а записать ключ для генератора XCA не позволяет. Более того, мне не удалось найти готовых решений, которые бы умели это из коробки. Aladdin SDK добыть не удалось, поэтому пришлось немного почудить.
Как уже было замечено ранее, взаимодействие с USB-ключом ведется через C:WindowsSystem32eToken.dll. Поэтому загружаем ее в DLL Explorer и ищем что-нибудь полезное. Взгляд цепляется за SAPI_OTP_Create, больше ничего и не надо, остается лишь найти пример работы с этой функцией.
Несложно заметить, что найденные примеры достаточно древние и не совсем предназначенные для нашей простой задачи. В итоге был выбран этот, поскольку обещается поддержка Python 3, а это значит, что доработать будет как минимум не мучительно.
Так родился модуль-набросок, в котором оставлены только релевантные функции: вход, удаление OTP, генерация нового ключа и запись этого ключа, добавлен выход. Попутно вылечены кое-какие трудноуловимые нюансы в духе неупакованной структуры типа CK_ATTRIBUTE (на 64-битной машине случилось раздутие полей нулями, и все сломалось). В нынешнем виде модуль работает под Windows 10 x64, под 11 не проверял.
Для использования этого модуля написана простейшая программка. Она создает либо заменяет настройки генератора OTP внутри брелока.
import etokenng
import pyotp, base64
param = {'debug': 'debug', 'userpin': b'12345ABCabc'}
enroller = etokenng.etng(param)
enroller.initpkcs11()
enroller.logintoken(1) ### Must be 0...
enroller.deleteOTP()
key = enroller.createKey()
enroller.createOTP(key = key, initial_count = 0)
enroller.logouttoken()
# Verify
hotp = pyotp.HOTP(base64.b32encode(key), initial_count = 0, digits = 6)
print(hotp.at(0)) ### Skipped? Why?
print(hotp.at(1))
print(hotp.at(2))
print(hotp.at(3))
print(hotp.at(4))
Внимание! Актуальный пароль вашего брелока должен быть подставлен в userpin перед экспериментами.
Из странностей — почему-то пришлось прибить гвоздями слот 1 (строка 8) вместо более логичного 0. Возможно, у кого-то будет все-таки 0 работать. Вторая странность в том, что брелок выдает пароли, начиная с первого, а не с нулевого, даже если разрешить нулевой в настройках. Поэтому hotp.at(0) не совпадает ни с чем, а hotp.at(1) отображается при первом нажатии на кнопку.
Если повезет, запускается и работает. Из зависимостей требует pyotp для проверки результата. Ключ генерируется самим брелоком и выдается открытым текстом в шестнадцатеричном виде (так как, к сожалению, HOTP не предусматривает механизмов асимметричной криптографии).
Выбор сферы применения генератора остается на откуп читателю. Например, можно еще сильнее усложнить аутентификацию на сервере с помощью одноразового пароля, но при использовании RSA-2048 с аппаратным ключом эта мера кажется избыточной. Впрочем, применение найдется, важно лишь учесть ограничения: брелок не умеет TOTP, выводит только 6 цифр и поддерживает только SHA1.
В итоге USB-ключ задействован во благо, ошибка 14 побеждена, eToken NG-OTP имеет шансы на вторую жизнь, а наработки из статьи потенциально переносимы и на другие задачи.
Автор: kaseiiro