
Репозиторий проекта: https://github.com/karen07/rp2040-totp-hid
Мне всегда было лень доставать телефон ради TOTP-кода, а вручную вводить длинные сложные пароли — удовольствие тоже сомнительное. С паролями эту проблему часто решают плохо: делают пароль попроще и покороче, чтобы его было удобно набирать. Но с TOTP так не получится — код живёт отдельно, его всё равно нужно открыть, посмотреть и перепечатать.
Так как небольшой опыт в программировании микроконтроллеров у меня уже был (Послушный YubiKey), я решил сделать маленький «вписыватель паролей»: USB-устройство, которое подключается к компьютеру, притворяется обычной клавиатурой и само вводит TOTP-код или сохранённый пароль.
Чтобы вводить пароль и TOTP так, будто их набирает пользователь, устройство должно уметь работать как USB HID-клавиатура. Для этого подходит не любой микроконтроллер: нужна поддержка USB device и HID. Мой выбор пал на RP2040-Zero — его легко достать, он недорогой, компактный, хорошо документирован, и по нему есть много туториалов.
Что купить и как спаять
Необходимо купить сам RP2040-Zero, но для работы TOTP требуется Unix time время с точностью хотя бы 5 секунд.

Для этого есть внешние платы, самым подходящим мне по форм фактору оказался DS3231.

Общение между RP2040-Zero и DS3231 идет через I2C.


У DS3231 можно отпаять черную колодку, и соединить RP2040-Zero и DS3231 через два пина, тем самым мы получим компактную 3D структуру и общую жесткость конструкции. Но при отпайке будьте аккуратные с батарейкой у DS3231, она может перегреться. Лучше вообще перед всеми работами батарейку отпаять, и уже припаять в самом конце.

Получается чип к чипу, рисков по нагреву и короткому замыканию нет.
Остается проводами подключить +3.3 и минус.


Прошивка для RP2040-Zero
Прошивка написана на C под Raspberry Pi Pico SDK и собирается через CMake. Для USB я использую TinyUSB: устройство объявляется как HID с двумя report ID. Первый report — обычная USB-клавиатура, через него я «печатаю» TOTP-код или сохранённый пароль. Второй report — служебный vendor-defined HID-канал для настройки через WebHID.
Когда WebHID-страница отправляет команду, она попадает в callback tud_hid_set_report_cb(). Первый байт пакета — это код команды, остальные байты — данные. Так я устанавливаю время в DS3231, записываю TOTP-секрет, записываю пароль, очищаю данные или возвращаю статус устройства.
Время хранится не во flash, а в RTC DS3231. При настройке браузер отправляет Unix time, а прошивка переводит его в обычные поля даты и времени: год, месяц, день, часы, минуты и секунды. Потом эти значения записываются в DS3231 в BCD-формате. При генерации TOTP происходит обратное: прошивка читает из DS3231 секунды, минуты, часы, дату, месяц и год, переводит BCD в обычные числа и собирает из них Unix time в UTC.
Сам TOTP считается стандартным способом: Base32-секрет декодируется в бинарный ключ, текущее Unix time делится на шаг 30 секунд, получившийся счётчик кодируется в 8 байт и подписывается через HMAC-SHA1. Потом из результата берётся динамическое усечение HOTP, число приводится к 6 цифрам через % 1000000, форматируется с ведущими нулями и отправляется в компьютер как нажатия клавиш USB-клавиатуры.
Как собрать прошивку
Подробно процесс сборки расписывать не буду, он стандартный для проекта на Pico SDK и CMake. Достаточно склонировать репозиторий с submodules и собрать release-вариант:
git clone --recurse-submodules https://github.com/karen07/rp2040-totp-hid.git cd rp2040-totp-hid cmake --preset release cmake --build --preset release
После сборки UF2-файл появится здесь:
build/release/rp2040_totp_hid.uf2
Дальше всё как обычно для RP2040: зажимаем BOOTSEL, подключаем плату по USB, отпускаем BOOTSEL и копируем rp2040_totp_hid.uf2 на появившийся диск RPI-RP2. После копирования плата перезагрузится уже с новой прошивкой.
Web GUI для настройки
Чтобы не писать отдельную desktop-утилиту, я сделал простую WebHID-панель. Она открывается прямо в браузере и позволяет настроить ключ через USB: записать TOTP-секрет, сохранить пароль, выставить время в RTC DS3231 и посмотреть текущее состояние устройства.

Работает это через WebHID, поэтому нужен браузер с его поддержкой, например Chrome или Edge. Пользователь открывает HTML-страницу, нажимает кнопку подключения, выбирает устройство в системном диалоге, и после этого страница может отправлять служебные HID-команды в прошивку.
Самое удобное — установка времени. Web GUI берёт текущее время с компьютера, отправляет его в устройство как Unix time, а прошивка уже переводит его в формат DS3231 и записывает в RTC. После этого устройство может считать TOTP автономно, без телефона и без связи с браузером.
Через эту же страницу можно записать Base32-секрет для TOTP и сохранённый пароль. После настройки браузер больше не нужен: ключ работает как обычная USB-клавиатура и по нажатию кнопки сам вводит TOTP-код или пароль.
Использование и безопасность
В итоге пользоваться устройством очень просто: одно нажатие BOOTSEL вводит текущий TOTP-код, двойное нажатие вводит сохранённый пароль. В обоих случаях для компьютера это выглядит как обычный ввод с USB-клавиатуры, поэтому важно заранее поставить курсор в нужное поле.
Конечно, я понимаю, что с точки зрения безопасности это не идеальное решение. Пароль и TOTP-секрет хранятся на самом устройстве, и если кто-то получит к нему физический доступ, он потенциально сможет их скопировать. Я отношусь к этому как к обычному физическому ключу: если потерять ключ от машины или дать его украсть, машину тоже можно угнать.
Поэтому такое устройство нужно хранить соответственно: не оставлять без присмотра, не подключать к чужим компьютерам и иметь возможность быстро отозвать пароль и TOTP-секрет. Для меня это в первую очередь DIY-проект и удобный «вписыватель» кодов и паролей, а не замена полноценному аппаратному security token.
Комментарии (14)

codecity
04.07.2026 13:41А плагин для браузера не писали, чтобы передать девайсу текущий сайт, куда вводится пароль?

Void-Cowboy
04.07.2026 13:41интересный проект. По идее можно даже "взросло" сделать. Вынести все ключи в отдельный крипточип специально под это заточеный. Добавить простенький tft дисплей для визуализации что бы можно было без веб-интерфейса переключатся по ключам. Опционально добавить сканер отпечатка пальцев.
Плюс я думаю можно просто "ключи" хранить. Отдельная кнопка что бы с TOTP переключится на текстовые ключи. Причем текстовые можно прямо в памяти хранить, просто криптовать внешним чипом и все будет безопасно максимально.
Как плюс, если взять что то по типу нордика или прочее нормальное беспроводное, то можно парить с телефоном/компом по блутузу и сделать вообще "беспроводным".

kenomimi
04.07.2026 13:41Люди заморачивались этим еще лет 10-12-15 назад, тут на хабре с пяток проектов было уже. Как показала практика, "гражданскому" рынку этот девайс попросту не нужен, так как пароли почти везде заменились смс-кодами. Зайти же к корпоратам или в госы, где оно может и было бы нужно, без больших связей/затрат врядли возможно (получить сертификацию не так-то просто, а без нее это просто игрушка).

inkelyad
04.07.2026 13:41"гражданскому" рынку этот девайс попросту не нужен, так как пароли почти везде заменились смс-кодами
С тех пор кое-что изменилось. Уже много кто (включая Гугл и сравнимые по крупности) говорит, что SMS им не нравятся и надо заменить. Тут бы им завалить рынок аппаратным токенами по себестоимости, чтобы в каждом ларьке лежали, но увы..

kenomimi
04.07.2026 13:41Близзарды к варику продавали одно время аппаратные TOTP-токены - эксперимент дальше этого не пошел. Ненкоторые банки их прямо в карту встраивали, тоже никого не заинтересовало вообще - продукт как появился, так и исчез... Ибо ответ прост - есть TOTP для телефонов в виде приложения, и кейсов, где он не применим, почти нет.
Если сейчас пытаться в такой продукт, то это должен быть именно гибрид TOTP + pkcs11 + парольный менеджер + защищенный картиридер, причем по цене до 100 баксов, частично опенсорсный для маркетинга (не сертифицированная версия), и при этом в закрытой версии сертифицированный как СКЗИ (или штатовский аналог). Выглядит не очень реально...

inkelyad
04.07.2026 13:41Если сейчас пытаться в такой продукт, то это должен быть
Да нет же. Это должна быть дешевая штука, которую покупаешь в супермаркете и которую просто регистрируешь в сервисе/привязываешь к сервису.
И вот это все: TOTP, pkcs11, кардридер - хоть и тешит гиковскую душу, но именно для массового продукта совершенно не нужно. Нужен простой и понятный ключ. В смысле - по модели использования. Ткнул в соответствующее место - тебя в сайт пустило. Как с физической дверью.

Void-Cowboy
04.07.2026 13:41смс пиздецки ненадежно
сам пользуюсь атентификатором для кодов, но физическое безопасное устройство я б купил.
просто все что есть на рынке оно коммерческое - стоит как крыло боинга и для его использования нужно отдельные полугодичные курсы заканчивать
не знаю ни одного решения что реально было бы удобным в повседневном использовании. Много раз думал сам написать но глубина сложности реализации отталкивала что бы сделать нормально, а просто чтоб было не надо.

inkelyad
04.07.2026 13:41Вынести все ключи в отдельный крипточип специально под это заточеный.
Которое есть Smart Card. И которые (специализированные под конкретные нужды) раздаются бесплатно кучками в виде банковских карт и SIM карт. А вот купить 'пустую по адекватной цене - какой-то неочевидный квест.
А так - смотри Mooltipass. (И цену его же). Только в подобных обсуждениях пользователь жаловался, что у товарищей с железом проблемы.

kenomimi
04.07.2026 13:41Ношу точно такую же штуку на базе Waveshare RP2350-Touch-LCD-1.28. Очень удобно. Изначально делал вообще ради эксперимента, можно ли сгенерить код для железки с нуля и "под ключ" при помощи claude. Можно, он даже с круглым экраном разобрался и не сломал UI... Причем это не ардуино-код, все на взрослом C++.
А вот с паролями я поступил так - при вводе пин-кода мы его просто запоминаем, и от него и внутреннего ключа генерим пароль. Неправильный пин-код? Получим неправильный пароль, то есть ручной перебор попросту невозможен.

nomorewar
04.07.2026 13:41Классная борда, но возникает вопрос: почему такое (юсб, микро дисплей) бывает только на RP или всевозможных ESP? Хотелось бы на базе STM32, чтобы новый камень не изучать (еще и СДК в придачу).

kenomimi
04.07.2026 13:41Скорее всего, оно спонсировано производителем чипа - банально дают хорошую скидку вендору девборд на чипы, если вообще не бесплатно подкидывают. Так как это шикарный маркетинг...
gibson_dev
Если взять 2350 то у него с безопасностью вроде как получше, 2040 просто вычитать можно.