Здравствуй, дорогой читатель!
Сегодня я погружу тебя в мир страшных аббревиатур: 2FA, TOTP, HOTP, HMAC, Hash, Base32, Base64, Xor, которые незаметно для нас делают нашу жизнь чуточку удобнее и безопаснее. Сразу не стоит пугаться, если всё это декомпозировать, то получается не так уж и сложно. Но обо всём по порядку.
Практически каждый из всех использует пароли для входа в разные сервисы, но в наше время пароль уже не является надежным фактором. Поэтому для большей безопасности придумали второй фактор аутентификации по альтернативному каналу, например, посредством отправки вам на телефон сообщения или звонка, или возможности генерирования вами одноразового кода, которым вы подтверждаете вход в сервис.
Одним из таких устоявшихся решений является одноразовый код на основе времени (Time-based One-time Password Algorithm, или TOTP). Те же Госуслуги или GitHub позволяют включить двухэтапную проверку cо вторым фактором аутентификации (2ФА или 2FA) посредством кода, который будет у вас генерироваться на некотором устройстве.
Одним из приложений для генерации одноразовых паролей для двухфакторной аутентификации является бесплатный Google Authenticator (это не реклама, просто сам пользуюсь)
Как-то подумал, а почему бы не сделать аналог на 1С. И сделал вызов самому себе )
Сразу скажу, что пару лет назад уже прикрутил 2FA к своему сайту на самописной CMS на PHP - но там это было в разы проще (хотя я PHP практически не знаю), т.к. в больших языках уже существует куча разного кода под почти все требования.
Итак, TOTP - это HOTP (HMAC-Based One-Time Password Algorithm), только с применением времени. Обычно, код меняется раз в 30 секунд. А HOTP - это алгоритм генерации на основе секрета, который использует для вычисления HMAC (Hash-based Message Authentication Code), а он, в свою очередь, вычисляет код на основе Хеш-функций - это своеобразные цифровые отпечатки одинаковой длины для входных данных любого размера. Короче, там запутывание и математика, благо не пришлось (почти) реализовывать хеш-функции, т.к. они в "стандартной библиотеке" 1с уже присутствуют, но работают только на сервере.
Пришлось написать свой алгоритм HMAC на 1С - он достаточно не сложный, понятно описан на Вики.
Самое мутное, что пришлось самому реализовать - это метод ПолучитьBase32ДвоичныеДанныеИзСтроки(). В эске уже есть ПолучитьBase64ДвоичныеДанныеИзСтроки(), но 64 было много, а 32 в самый раз )
BaseN - это алгоритмы, которые переводят двоичные данные в читабельный текст, алфавит которого состоит из N символов. Плюс в том, что его можно легко передавать, а минус в том, что размер данных увеличивается (чем меньше N, тем больше размер, для base64 прирост на треть, а для base32 прирост на 60%).
Про простые вещи, типа UnixTime, преобразования между системами счисления (2, 10, 16) и простого ИсключающегоИЛИ не буду рассказывать, т.к. это всё детский кодинг.
Итого у нас получается: есть некая секретная строка, хранящаяся на сервере и у вас, на нее натравливается алгоритм, который вычисляет от неё Base32, затем берется номер 30-ти секундного интервала, начиная от первого пришествия от начала отсчета Unix-времени, на основании этого вычисляется HMAC, ну а из него уже простыми манипуляциями получаем тот самый одноразовый токен, который вы вводите в сервисе, а сервис проделывает тот же самый расчет и сравнивает ваш одноразовый пароль с тем, что он насчитал.
Когда алгоритм получения одноразового кода из секретной строки был готов, дальше стал создавать расширение, которое можно подключить к любой базе (даже пустой).
Расширение подключается без снятия галок секьюрности.
Разрабатывал на другой конфе, поэтому логотип подсистемы здесь выглядит будто бы не из этого набора )
Если нажать на ссылку в панели навигации, то откроется форма входа, на которой надо установить Мега%Длинный=Супер-Пупер#Пароль. Он будет использоваться для шифрации и дешифрации секретов разных сервисов.
Да, пришлось реализовать свой примитивный алгоритм шифрования и даже самописный легкий хеш, который работает на клиенте. МастерПароль с клиента никуда НЕ уходит и нигде НЕ хранится, его надо вводить при каждом открытии жёлтого аутентификатора. Т.к. я не криптолог, то я не советую использовать алгоритм шифрования для ваших финансов, а заюзать, например, шифрование на основе криптодвижка, встроенного в платформу. Вроде бы мой алгоритм кажется достаточно надежным. Но если кто-нить сможет математически его раскритиковать, или написать утилиту для взлома, я бы с удовольствием на это поглядел бы )
После установки зашифрованной кодовой строки, которая будет служить проверкой при последующем входе, можно уже открыть главную форму аутентификатора:
Слева видим шкалу, которая сбрасывается раз в 30 секунд, соответственно, одноразовые коды тоже "живут" 30 секунд, пока "градусник" убывает, а потом коды протухают и генерятся новые.
Для добавления новой записи жмём соответствующую кнопку:
Секрет вводится как есть, а при записи алгоритм его пошифрует МастерПаролем и запишет в базу уже "криптостойким". Размер секрета должен быть кратен 8 и содержать только символы из base32-алфавита: английские буквы и цифры от 2 до 7 включительно.
Расширение проверялось на платформе 8.3.23, но будет работать, начиная с 8.3.10+
Код полностью открыт, можете использовать его в своих разработках, но со ссылкой на автора.
На разработку данного решения я потратил 7 вечеров (3 на алгоритм одноразового пароля, 3 на расширение, в том числе на разработку своего криптоалгоритма, и 1 на написание данной публикации).
Если вам понравилось, то не забудьте поддержать автора хотя бы плюсом (+), чтобы я дальше не ленился делать интересные вещи.
Ещё больше дичи в моём профиле или на гитхабе.
Проверено на следующих конфигурациях и релизах:
- 1С:Библиотека стандартных подсистем, редакция 3.1, релизы 3.1.10.383