Получение TOTP-токенов на умнейших из тупых часов

в 13:00, , рубрики: Без рубрики

Получение TOTP-токенов на умнейших из тупых часов - 1


Недавно получил свой заказ с новой логической платой от Sensor Watch для вездесущих классических часов Casio F-91W. Модель F-91W не требует представления. Это наверняка самые популярные кварцевые часы в мире, которых в общей сложности было продано около 90 миллионов.

В купленной мной плате Sensor Watch оригинальный кварцевый механизм F-91W заменён новым мозгом на базе ARM Cortex M0+. В ней используются оригинальный ЖК-дисплей, толкатели для кнопок и пьезодинамик. Эта программируемая плата, и проект Sensor Watch также предоставляет простой в плане модификаций набор циферблатов и небольшие дополнительные приложения.

В устройстве нет Bluetooth, но комбинация легковесного, проверенного временем корпуса с долгоживущей батареей и функциональностью, которую без проблем можно воссоздать дома, на удивление великолепна. Где-то за час я смог: заменить плату, настроить двухфакторную аутентификацию (2FA) для своих аккаунтов Google и GitHub, чтобы получать наиболее часто используемые OTP-коды прямо на своё запястье, и написать циферблат-счётчик, который можно использовать для отсчёта шагов или взмахов при гребле на лодке.

Хакать такой девайс — одно удовольствие. Причём для него есть даже эмулятор на основе WASM, который упрощает тестирование на ПК и позволяет поиграться с различными кастомными сборками, например, с моей (в оригинале статьи доступна интерактивная версия часов, — прим. пер.):

Получение TOTP-токенов на умнейших из тупых часов - 2

Нажмите MODE один раз, чтобы перейти на экран 2FA-токенов. Сейчас ALARM выполняет переключение между токенами Google и GitHub. Не беспокойтесь, я заменил свои реальные секреты TOTP фиктивными значениями. Нажмите ещё раз MODE, чтобы перейти на разработанный мной циферблат со счётчиком. Теперь периодически нажимайте ALARM, чтобы измерять частоту в минуту или иной интересующий вас показатель. Среди прочих циферблатов в этой сборке присутствуют мировые часы, калькулятор времени восходов/закатов, индикатор лунных фаз, показания температурного датчика в реальном времени, установщик формата 24h и режим настройки даты/времени. В дереве исходного кода movement репозитория Sensor Watch есть и много других крутых циферблатов, включая тонометр и модель Солнечной системы.

Весь процесс апгрейда модуля F-91W хорошо описан в блоге Джона Грэхама-Камминга — я даже заказал один экземпляр его крутых оранжевых часов, чтобы переставить туда новую плату.
Ниже я поделюсь о том, как перенести ваши секреты TOTP в сборку, и расскажу о своей разработке нового циферблата.

Циферблат TOTP

Этот циферблат генерирует одноразовые пароли с привязкой ко времени (двухфакторные коды аутентификации), позволяя безопасно авторизовываться на многих популярных сайтах (например, Google и GitHub). Механизм TOTP (time-based one-time password) представляет собой алгоритм, который генерирует одноразовый пароль (OTP), обеспечивая его уникальность на основе текущего времени.

Нажмите кнопку ALARM для переключения между настроенными сайтами/секретами TOTP.
Этот циферблат поддерживает несколько секретов сайтов, которые нужно извлекать из QR-кодов TOTP и добавлять в его исходный код следующим образом:

  1. Получать секрет TOTP или QR-код от сайта, для которого требуется сгенерировать коды.
  2. Если у вас есть только QR-код, сайт Штефана Сандина позволит извлечь его секрет в кодировке Base32 — это будет буквенно-цифровая строка из примерно 32 символов.
  3. Для добавления полученного секрета в код циферблата нужно преобразовать его в шестнадцатеричные байты. Сделать это можно на сайте cryptii.com. Обратите внимание, что TOTP-секрет нужно вводить в верхнем регистре.
  4. Наконец, вам нужно взять полученные шестнадцатеричные байты, добавить их в исходный код циферблата TOTP и заново скомпилировать movement:

▍ Редактирование totp_face.c

Вы можете решить удалить демо-ключи. Предположим, вы захотите добавить ключ в конец списка. В таком случае прибавьте единицу к числу в этой строке:

static const uint8_t num_keys = 2;

Добавьте шестнадцатеричные байты, полученные на шаге 3, в конец этого массива, разделив их запятыми и указав в начале каждого 0x.

static uint8_t keys[] = {
   // Добавьте шестнадцатеричные байты ключа
};

Добавьте в конец этого массива размер секрета (количество только что внесённых шестнадцатеричных байтов):

static const uint8_t key_sizes[] = {

Добавьте ещё одну запись 30 в конец этого массива.

static const uint32_t timesteps[] = {

Добавьте метку для секрета. Например, если он относится к аккаунту Google, можете указать в качестве неё символы { 'g', 'o' }.

static const char labels[][2] = {

Вот и всё — наслаждайтесь всеми удобствами кодов TOTP на своём запястье!

▍ Написание собственного циферблата-счётчика

Весь код находится в этом пул-реквесте, который я отправил в основной проект.

Написать эту функциональность оказалось, на удивление, легко — практически вся реализация уместилась в одной основной функции.

bool ratemeter_face_loop(movement_event_t event,
                         movement_settings_t *settings,
                         void *context) {
    (void) settings;
    ratemeter_state_t *ratemeter_state = (ratemeter_state_t *)context;
    char buf[14];

Эта функция обрабатывает все нужные вам события нажатий кнопок, а также каждый тик часов.

    switch (event.event_type) {

При этом, если вас интересует измерение промежутков времени, обработка анимаций или нечто аналогичное, то циферблат может запрашивать частоту тактов.

В дереве movement присутствует вспомогательная функция watch_display_string, которая как умеет старается отрисовывать буквенно-цифровую строку для различных элементов дисплея Casio, состоящих из 7 и более сегментов. При попытке вывести на эту ограниченную поверхность произвольные строки возникают всяческие проблемы, но всё это достаточно хорошо описано в документации.

Итак, перечислю все состояния часов, которые нас интересуют.

При активации циферблата в индикаторе дней отображается RA.

        case EVENT_ACTIVATE:
            watch_display_string("ra          ", 0);
            break;

При нажатии MODE происходит переключение на следующий циферблат.

        case EVENT_MODE_BUTTON_UP:
            movement_move_to_next_face();
            break;

При нажатии LIGHT включается подсветка.

        case EVENT_LIGHT_BUTTON_DOWN:
            movement_illuminate_led();
            break;

А теперь самое важное… При нажатии ALARM:

  1. Обновляется вычисленная частота на основе промежутка между текущим нажатием кнопки и предыдущим.
  2. Сбрасывается счётчик тактов (часть специального состояния циферблата, который я написал).
  3. Сбрасывается частота быстрых тактов (эта константа определена как 1/16 секунды).

case EVENT_ALARM_BUTTON_DOWN:
            if (ratemeter_state->ticks != 0) {
                ratemeter_state->rate =
                    (int16_t)(60.0 / 
                        ((float)ratemeter_state->ticks /
                         (float)RATEMETER_FACE_FREQUENCY));
            }
            ratemeter_state->ticks = 0;
            movement_request_tick_frequency(RATEMETER_FACE_FREQUENCY);
            break;

И, наконец, при каждом тике… Обновляется дисплей, отображая текущую частоту или «Hi», если частота больше 500/минуту, либо «Lo», если она составляет 1/минуту. При этом также инкрементируется счётчик тактов.

       case EVENT_TICK:
            if (ratemeter_state->rate == 0) {
                watch_display_string("ra          ", 0);
            } else {
                if (ratemeter_state->rate > 500) {
                    watch_display_string("ra      Hi", 0);
                } else if (ratemeter_state->rate < 1) {
                    watch_display_string("ra      Lo", 0);
                } else {
                    sprintf(buf, "ra  %-3d pn", ratemeter_state->rate);
                    watch_display_string(buf, 0);
                }
            }
            ratemeter_state->ticks++;
            break;

Вот и всё! Проект получился проще и интереснее, чем я ожидал.

Если вам понравился этот апгрейд, можете тоже заказать себе плату Sensor Watch с Oddly Specific Objects. Я с ними никак не аффилирован, просто считаю, что Джо реализовал действительно крутую идею.

Автор: Дмитрий Брайт

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js