Казалось бы – чем больше цифровизация проникает в нашу жизнь, тем удобнее эта жизнь становится. Увы, у удобства есть антипод – безопасность. Чем проще вам организовать доступ к своему фиатному или крипто-счету, фотоархиву, рабочим документам – тем выше риск, что этим доступом воспользуется тот, кому это вовсе не положено. В эпоху “платежей в один клик” с мобильных устройств (а то и вовсе без кликов) эти риски особенно высоки, понятны и очевидны. Существует множество способов с ними бороться, и сегодня я хотел бы поделиться с вами одним из них – это мой опыт внедрения двухфакторной аутентификации с помощью JavaCard для мобильного приложения на базе Android.
Базовые знания об аутентификации
Поскольку я задумывал эту статью как доступную всем и каждому, то давайте начнем с азов. Аутентификация – это процедура проверки подлинности в информационных системах. Логины, пароли, пин-коды, отпечатки пальцев и распознавание радужки глаза – все это атрибуты аутентификации. В современном беспокойном мире быстро стало понятно, что полагаться только на что-то одно из этого списка рискованно. Поэтому в тех случаях, когда на кону что-то особенно важное (например, деньги или конфиденциальные данные), отраслевым стандартом стала аутентификация с одновременным использованием двух различных факторов, также известная как 2FA.
Слово “различных” я выделил неспроста. Почему – очень скоро станет понятно. Итак, двумя различными факторами могут быть:
Фактор #1 – это то, что пользователь знает: пароль или пин-код.
Фактор #2 – это то, чем пользователь владеет: устройство, смарт-карта, USB-токен.
Таким образом, даже если пароль “утек”, похищен, перехвачен или настолько примитивен, что поддается простому подбору, у нас всегда остается второй рубеж обороны: физическое устройство, без которого доступ к информации невозможен.
Почему SMS/Push может быть недостаточно
Фактор владения можно использовать по-разному. Часто принято использовать в качестве второго фактора подтверждение через код, присланный в SMS или в Push приложения аутентификации (например, Google Authenticator). Получение такого кода подтверждает факт владения смартфоном. Удобно? Да. Быстро? Несомненно. Надежно? А вот тут все сложнее… В случае мобильного приложения сам факт владения не несет особой ценности, ведь SMS или Push приходит на тоже самое устройство, владельца которого необходимо идентифицировать. Специальное приложение аутентификации тоже ничего принципиально не меняет: оно установлено на том же устройстве, где “живет” и наше с вами приложение.
Представим себе, что злоумышленник получил доступ к устройству физически или удаленно. Например, убедив пользователя дать доступ к TeamViewer или использовав уязвимости операционной системы. Так он становится обладателем второго фактора аутентификации. Остается только получить пароль к системе (первый фактор) и можно легко и непринужденно выдавать себя за законного пользователя.
Выбор в пользу JavaCard
Так мы постепенно приходим к мысли, что ОС смартфона никак не может быть полноценным вторым фактором. Как же исправить эту уязвимость? Например, использовать в качестве второго фактора JavaCard. История этой технологии уходит корнями в глубокую древность, а именно в 1977 год, когда французский инженер и криптограф Мишель Угон впервые впихнул в пластиковую карту микропроцессор и модуль памяти – то есть изобрел смарт-карту в нынешнем виде. Впоследствии патент на карты этого типа оказался в руках одного из подразделений международной нефтесервисной компании Schlumberger, которая и представила первую версию платформы JavaCard в 1996 году.
После цепочки спин-оффов, слияний, поглощений и смен брендов (в их числе Axalto и Gemalto, бывшие в свое время ведущими производителями смарт-карт), физическая часть технологии на сегодня находится в руках французского оборонного концерна Thales. Программная часть ведет свою историю от подразделения IBM в швейцарском Цюрихе. Именно его стараниями в девяностых годах ХХ века появилась первая версия операционной системы для платформы JavaCard. Впоследствии спецификации этой ОС стали поддерживаться Sun Microsystems, которая ныне является подразделением Oracle, одного из грандов мировой IT-индустрии. Одним словом, JavaCard – это одно из самых заслуженных, проверенных и ведущих решений на рынке позволяющих построить безопасное решение на своей платформе.
Java-апплет + Android-приложение
Стандарт JavaCard позволяет загружать Java-приложения (апплеты) на карту и выполнять их средствами платформы и внутренней ОС карты. Программный код в этой среде исполняется только по запросу NFC-ридера. Коммуникация происходит в формате APDU протокола.
Наше решение состоит из двух частей – апплета и NFC ридера. Основная идея – хранить некий секрет на карте и иметь возможность его проверки на клиентском устройстве. В качестве такого алгоритма можно использовать механизм сертификата открытого ключа.
Итак, Java-апплет содержит код, который выполняет следующие функции:
Генерирует и хранит пару public и private ключей. Безопасность обеспечивается тем, что private ключ никогда не покидает карту и может быть только удален и перезаписан
Выпускает цифровой сертификат
Передает подписанный сертификат ридеру
В свою очередь, приложение на Android:
Отправляет APDU команду по NFC на запрос подписанного сообщения
Проверяет публичным ключом цифровую подпись полученную с карты
Также Android приложение может иметь дополнительный пин-код, который верифицируется на карте. Отправка сообщения с карты происходит только при валидном пин-коде.
Дополнительно предусматриваются сервисные APDU команды которые позволяют:
Сбросить и создать заново пару public и private ключей на карте
Получить public ключ из JavaCard
Для работы с NFC в Android приложении можно использовать соответствующие инструменты SDK. В нашем случае использовались карты ACS стандарта ISO 14443. В Android за коммуникацию с ним отвечает интерфейс IsoDep:
Резюме
В сухом остатке, этот проект удвоил значимость фактора владения: для гарантированного доступа к приложению пользователь должен обладать уже не только смартфоном, но еще и смарт-картой. Если вы смотрели фильмы или читали книги о приключениях Гарри Поттера, то помните, что очень похожей стратегии придерживался Лорд Волан-де-Морт, пытаясь гарантировать себе бессмертие. Разбив свою душу на куски и поместив их в семь крестражей, Тот-Кого-Нельзя-Называть был уверен в своей неуязвимости. И все мы помним, как бесславно закончилась его история.
Что ж, в реальной жизни дела обстоят примерно так же. Число факторов аутентификации (с учетом возможного их дробления, как было показано в этой статье) в принципе можно довести до числа крестражей. Но важно также, чтобы пользователь не повторял ошибки Сами-Знаете-Кого. Держать все время при себе змею Нагайну (крестраж #6) – это все равно, что хранить бумажку с пин-кодом в кошельке рядом с кредиткой. А маниакальное стремление поймать Гарри Поттера (крестраж #7) так похоже на привычку открывать без разбора все ссылки и документы, которые приходят в электронную почту или в мессенджеры.
Поэтому закончить эту статью логично тем же, с чего она начиналась: удобство – это антипод безопасности. Так что, проектируя решения, направленные на безопасность, нужно исходить из целесообразности и учитывать неистребимую тягу людей к удобству. Поверьте, многие из них будут хранить смарт-карту в одном чехле со смартфоном…
Что еще почитать
Базовые вещи об аутентификации: https://en.wikipedia.org/wiki/Electronic_authentication
Многофакторная аутиентификация: https://en.wikipedia.org/wiki/Multi-factor_authentication
О смарт-картах (цикл статей): https://habr.com/ru/articles/367229/
APDU протокол: https://en.wikipedia.org/wiki/Smart_card_application_protocol_data_unit
Апплеты JavaCard: https://www.oracle.com/java/technologies/java-card/writing-javacard-applet.html
Сертификат открытого ключа: https://en.wikipedia.org/wiki/Public_key_certificate
Книга "Технология Java Card для смарт-карт. Архитектура и руководство программиста"