Распознаём изображение с токена при помощи камеры

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

    и сказали: жмёшь кнопку, смотришь цифры, вводишь пароль и радуешься. «Безопасность, конечно, превыше всего, но и о комфорте забывать не следует» — примерно так подумал я и провёл ревизию имеющегося у меня электронного хлама.

    (Честно говоря, мне давно хотелось отвлечься от программирования и поковыряться в железяках, поэтому моя лень — не единственный мотиватор во всей этой затее).

    Анализ технического задания и подбор компонентов



    Первым делом на глаза мне попалась старая веб-камера «Logitech QuickCam 3000», отправившаяся в «хлам» в связи с покупкой ноутбука со встроенной веб-камерой. План созрел моментально: снимаем камерой циферки с токена, распознаём их на компьютере и… Профит! Дальше был найден сервопривод (ну не нажимать же кнопку на токене каждый раз руками, правда?), старый USB-хаб (в моём ноутбуке всего два USB-порта, и один из них постоянно занят USB-Ethernet адаптером), и плата Arduino, неизвестно каким образом у меня оказавшаяся. В качестве корпуса для своего девайса я решил использовать конструктор «Лего», купленный впрок моему годовалому сыну (кажется, теперь я понимаю, почему жена ехидно ухмыльнулась при покупке).

    К сожалению, фотографий донорских девайсов в целости и сохранности у меня нет, поэтому я могу «похвастаться» только устройством в сборе:



    Принципиальная схема и прошивка микроконтроллера



    Собственно, всё до смешного просто (я даже схему рисовать не буду): USB-хаб, к которому подключена веб-камера и ардуина. К ардуине подключен сервопривод (через ШИМ). Вот и всё.Исходный код программы, которая заливается в ардуину, тривиален: github.com/dreadatour/lazy/blob/master/servo.ino
    Ардуина ждёт букву 'G' на ком-порт, и при её поступлении дёргает серву туда-назад. Задержка (500мс) и угол наклона сервы были подобраны экспериментальным путём.

    Выбор языка программирования и анализ существующих библиотек «компьютерного зрения»



    Единственным языком программирования, которому бы я доверил такую сложную задачу, как «компьютерное зрение» — благославленный Python. Благо в нём, практически из коробки, есть биндинги к такой славной библиотеке, как OpenCV. Собственно, на этом и остановимся.

    Алгоритм распознавания кода токена



    Я буду давать ссылки на куски кода, которые отвечают за описываемый функционал — на мой взгляд это оптимальный формат подачи информации. Весь код можно посмотреть на гитхабе.

    Для начала берём изображение с камеры:


    Облегчаем себе задачу: камера неподвижна относительно основы, токен может двигаться в своём лотке совсем незначительно, поэтому находим границы возможных положений токена, обрезаем кадр с камеры и (исключительно для нашего удобства) поворачиваем изображение на 90˚:


    Дальше делаем некоторые преобразования: конвертируем получившееся изображение в grayscale и находим границы с помощью детектора границ Канни — это будут границы ЖК-экрана токена:


    Находим контуры на полученном изображении. Контур представляет собой массив линий — отбрасываем линии меньше определённой длины:


    С помощью тупого алгоритма определяем четыре линии, ограничивающие наш ЖК-дисплей:


    Находим точки персечения этих линий и выполняем несколько проверок:
    • проверяем, чтобы длина вертикальных и горизонтальных линий примерно совпадала друг с другом и чтобы длина линий примерно совпадала с размером ЖК-дисплея (который мы вычислили экспериментальным путём)
    • проверяем, чтобы диагонали были примерно равны (нам нужно прямоугольник — ЖК-дисплей)

    Далее находим угол, на который повёрнут наш токен, поворачиваем изображение на этот угол и вырезаем изображение ЖК:


    Самое сложное позади. Теперь нам нужно повысить контрастность полученного изображения. Для этого мы запоминаем изображение пустого ЖК-экрана (до нажатия на кнопку токена), и просто «вычитаем» это изображение из картинки с цифрами (после нажатия на кнопку):


    Получаем чёрно-белое изображение. Для этого с помощью ещё одного тупого алгоритма находим оптимальный порог, который будет разделять все пиксели на изображении на «чёрные» и «белые», конвертируем изображение в Ч/Б и вырезаем символы:


    Ну а дальше просто распознаём цифры. Нам нет смысла мучаться с нейронными сетями и прочими штуками, т.к. у нас семисегментный индикатор: есть семь «точек», по которым однозначно определяется каждая цифра:


    На всякий случай распознаём цифры с нескольких кадров: если три кадра подряд мы получили одинаковый результат — считаем, что распознавание прошло успешно, выводим результат с помощью программы «growlnotify» пользователю и копируем полученный код в буфер обмена.

    Видео работы девайса


    Осторожно, звук!


    Исходный код целиком
    Поделиться публикацией
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама
    Комментарии 59
    • +12
      Dreadatour — молодец!
      • –3
        Отлично сделано. Ждем коммерческую версию :)
      • +1
        Я так и не понял как «из коробки» начать работать с опенцв в питоне… :-( Как?
        • +2
          всё предельно просто:
          brew install opencv

          а дальше
          import cv

          и поехали…
          • 0
            почти
            тока brew неизвестно что такое. Гугл ищет софт для пивоварения. А вот это меня вообще сделало бояться:
            «To cut this short, here is what you need to get that Python running: brew install python»

            Кто такой брю?
            • +2
              Брю это пакетный менеджер для мака. Вам нужно наверно apt-get install opencv
          • 0
            bluehat.me/blog/2011/09/10/python-installation-via-homebrew/
            А, блин, это что-то линуксовое…
            Под виндой у меня траблы. Под 7-кой.
            • 0
              А…
              о… Homebrew is the easiest and most flexible way to install the UNIX tools Apple didn't include with OS X.
              • +9
                Про windows ничего не знаю, извините
                • 0
                  На Win просто устанавливается пакет путём загрузки необходимого исполняемого файла. Собственно, ниже ссылочки дали.
              • 0
                Во-во, самый лучший вариант. Да помимо OpenCV там ещё куча разных библиотек есть.
                • –3
                  я крутой, у меня python 3
                • +3
                  Мне кажется что этому девайсу надо сделать стенки чтобы не было бликов на экране от окон и пр. + добавить подсветку (например светодиодом запитанным от той-же ардуины) во время съёмки…
                  А так — очень даже интересно… правда нагляднее было бы всё-же с кодом в статье, а не по ссылкам :)
                  • +2
                    Стенки делать нет смысла, т.к. бликов не бывает — камера строго перпендикулярна ЖК-экрану, поэтому бликовать там нечему.
                    А вот тень от краёв «окошка» экрана иногда мешает распознавать картинку — тут вы правы, нужен светодиод. Я даже экспериментировал с подключенным через второй ШИМ (для управления яркостью) светодиодом, но вмечатляющих результатов не добился — если направлять светодиод строго в экран, он очень сильно бликует, если же подсвечивать экран сбоку, появляется та же тень. Нужен рассеиватель.

                    В общем, надо думать, экспериментировать, а мне, если честно, уже лень ;)
                    • +1
                      два диода с двух сторон и белая бумага в качестве рассеивателся.
                  • –4
                    Если б Вам разрешили разобрать токен, то можно б было обойтись одной ардуиной — узнавать цифры с помощью анализа напряжений на выводах ЖК дисплея.
                    Но вот мощности ардуины не хватит представиться USB-клавиатурой (чтоб ввести пароль в домен)
                    Хотя Ваша конструкция напоминает считыватель TouchMemory с привязанной к нему скотчем таблеткой — профанация всей идеи безопасности…
                    • 0
                      Никто не мешает забирать токен с собой, покидая рабочее место, что, думается мне, и было специально предусмотрено конструкцией.
                      • +1
                        Ну разобрать токен, не так уж и просто, как кажется на первый взгляд, об этом позаботились его разработчики.
                        • +8
                          Разобрать токен никто не даст.
                          Да и «анализировать напряжение на выводах ЖК дисплея» сильно сложнее моей поделки, если честно.

                          Ардуина тут вообще, фактически, для красоты, как на известной картинке. Если бы была нужна USB-клавиатура, никто не помешал бы мне взять нормальную AVR'ку (или даже ARM) и сотворить всё, что душе угодно.

                          Кто куда привязан? Какая профанация? Ничего не понял. Вот, на всякий случай, ещё одна фотка, — возможно, вы не так всё поняли.

                        • 0
                          а зачем распознавать? у нас для такого же просто фотки с вебкамеры на http-сервер выкладываются
                          • +1
                            Ну чтобы надо зайти на сервер — нажал хоткей, дождался распознавания, нажал «вставить» в поле пароля и всё.

                            А у вас зачем фотки на http-сервер выкладываются? о_О
                            • –1
                              открыл закладку — посмотрел пароль, ввел
                              • +5
                                Ууу, это долго. Так можно и взять токен в руку, посмотреть пароль, ввести. А мне так лень )
                                • +3
                                  токен на другом континенте :)
                                  • +3
                                    спросонья не понял шутки =)

                                    а как же безопасность, все дела? теряется весь смысл токена
                                    • +2
                                      Адрес сервера меняется каждые две минуты.
                                      • +16
                                        и чтобы его узнать, нужен еще один токен :)
                            • +1
                              для минимизации телодвижений, надо ещё после распознания автоматически вставлять текст в активное поле ввода
                            • +17
                              Пожалуй, пора делать токен в виде каптчи — смазанной и прыгающими цифрами
                              • +13
                                Только нашим безопасникам не говорите, пожалуйста? ;)
                                • +1
                                  А еще лучше загадку или ребус. Условие, естественно, замазать как в каптче.
                                  • +1
                                    Это только ускорит популярность таких кустарных приборов.
                                    Капчи гораздо проще распознавать алгоритмом, чем глазом.
                                  • 0
                                    Скажите, пожалуйста, а как вы освоили OpenCV под Python?

                                    Я пишу курсовую по обработке изображений. Но OpenCV я как-то не потянул — не нашел толковых мануалов. В итоге ограничился достаточно простым но банальным PIL :(
                                    • +2
                                      У OpenCV не самая лучшая, но достаточно внятная документация с хорошим поиском (пример запроса по уловию «Canny»).

                                      В исходниках OpenCV можно найти замечательные примеры (директория «samples») — на питоне в том числе.
                                      Я просто грепал название нужной мне функции в этой директории и находил примеры использования.

                                      Ну и google (который, зачастую, выводил меня на stack overflow).
                                      • +1
                                        Learning OpenCV. Где взять в оригинале, сами знаете. Есть ещё фанатский русский перевод.
                                      • +4
                                        Веб камеры довольно шумные, особенно если освещённость не очень. Качество картинки можно улучшить интегрированием — ну то есть захватить не один кадр, а несколько, сложить их, а потом посчитать среднее. Обычно берут количество кадров, равное степени двойки — скажем 8 или 16 и т.д. — тогда деление можно заменить сдвигом. Соотношение сигнал/шум несколько улучшится. Но если и так работает, можно и не заморачиваться.
                                        • 0
                                          тогда проще поставить 1-2 светодиода для подсветки, качество вырастет намного!
                                          Кстати легкое смещение токена от оси камеры тоже может повысить контраст, ведь у таких жк дисплеев есть углы где контраст максимален, а в противоположных углах наоборот падает.
                                          • +1
                                            Андрей, я думал про интегрирование, но решил не заморачиваться особо, и решил задачу «в лоб».
                                            Путей оптимизации и улучшения алгоритма масса, — когда мне будет скучно, я, возможно, вернусь к этой задаче.
                                          • +3
                                            Вова молодец! :-)
                                            • 0
                                              Спасибо. Как раз собираюсь разбираться с OpenCV. :)
                                              • +1
                                                М-м-м… узнаю обои
                                                • +2
                                                  Куда смотрит ваш security manager?
                                                  • +1
                                                    Ну если вы попробуете объяснить мне, в каком месте здесь нарушена безопасность, — я обещаю, что привлеку его к проблеме.
                                                    • +3
                                                      Замечательная статья и замечательный способ повышения удобства. Но давайте я попробую на пальцах объяснить, в каком месте нарушается безопасность.

                                                      Основная идея автономных OTP-токенов в том, что физически разделяются «каналы» генерации и доставки секрета в момент аутентификации. То есть у вас для генерации секрета используется токен, а для его доставки — компьютер и сеть.
                                                      В этой связке недоверенными являются компьютер и сеть передачи данных. Именно поэтому им не позволено генерировать или хранить секрет. Это делает автономное устройство, на которое недоверенный компьютер или недоверенный субъект в сети никак (теоретически) не может повлиять, потому что для генерации секрета нужно физически нажать кнопку и ручками ввести одноразовый пароль. А у компьютера или субъекта в сети ручек нету.

                                                      Что Вы делаете. Вы даете недоверенному компьютеру возможность управлять генерацией секрета, то есть даете ему ручки. Весь смысл автономного OTP-токена коту под хвост :)

                                                      Но в оправдание можно сказать что
                                                      — это не массовый продукт, уязвимости в вашем ПО и принципах работы искать никто не будет
                                                      — токен всегда можно забрать с собой (это нужно делать обязательно, когда Вас нет)
                                                      — это удобно :)

                                                      Но Ваш Security Manager, если ему не зря платят зарплату, должен Вас очень сильно отругать за такое изобретение.
                                                      • Я вмешаюсь в разговор и блесну отсутствием каких-либо знаний в области ИБ, извините. Так вот, с чего вдруг в данном случае компьютер стал недоверенным? Если его как-то скомпрометировали, то не проще ли поставить кейлоггер/сниффер, либо воспользоваться поднятой ssh-сессией, чем пытаться найти уязвимость в ПО распознавалки?
                                                        • 0
                                                          Эта схема работает только если есть токен в устройстве. Процесс генерации сопровождается шумом и визуально виден, т.е. «тихой сапой» генерировать не получится. Уходя, токен просто забирается.
                                                          • –1
                                                            Спасибо за развёрнутый ответ и попытку объяснить суть проблемы.

                                                            На мой взгляд в ваши рассуждения закралась ошибка, вот тут: «Вы даете недоверенному компьютеру возможность управлять генерацией секрета». В моём случае компьютер ничего не генерирует — он всё так же является «каналом» доставки, — ключ генерируется токеном по запросу пользователя. Описываемое в статье устройство — всего лишь замена канала доставки под названием «человек» на канал доставки под названием «мой девайс».

                                                            Поправьте меня, если я ошибаюсь.
                                                            • +2
                                                              Если я правильно понял суть Вашего девайса, то происходит следующее: по команде из компьютера (например, по нажатию short key), девайс жмет на кнопку на токене снимает результат, после чего изображение передается в компьютер на анализ.

                                                              Таким образом, компьютер управляет событием генерации и получает результат. Причем Ваша программа выводит результат в машиночитаемом виде (но это уже не принципиально).

                                                              Идеологически, недоверенному компьютеру (вирус, вредоносное ПО, шпионский софт и пр.) ничего не мешает без Вас послать команду на генерацию OTP и получить его значение. Вот и нарушение безопасности.

                                                              Об оговорках («кому это надо?», «можно унести токен с собой», «процесс генерации видно» и пр.) я писАл выше. Но мы сейчас руссуждаем о принципах :)
                                                              • 0
                                                                Да, теперь я понял о чём речь.
                                                                Согласен со всеми приведёнными доводами.
                                                                К счастью, есть тысячи более простых (но, тем не менее, практически — невозможных) способов получить доступ к системе и я могу спать спокойно.
                                                                • +1
                                                                  Нужно просто сделать аппаратную кнопку активации процесса вместо управления с компьютера.
                                                                • 0
                                                                  как вариант, ранее человек самостоятельно управлял событием «генерация токена».

                                                                  Сейчас же можно удалённо запустить данную процедуру. Тем самым исключая контроль человека над этим независимым участком процесса аутентификации и авторизации.

                                                            • Радовался и хлопал в ладоши, когда ему показали устройство.
                                                            • +11
                                                              Томас Эдисон в свое время, работая оператором связи на ЖД, вынужден был каждые 30 минут отстукивать азбукой Морзе «я не сплю», чтобы показывать, что готов принимать сообщение. Ясное дело, ночью ему хотелось спать и он придумал устройство, которое отстукивало нужный код, если провернуть колесо с рукояткой. Затем он договорился с ночным сторожем, чтобы тот каждые 30 минут подходил и поворачивал ручку. :-)
                                                              И можно было долго спать. Правда, он спалился на том, что ночью нужно было принять сообщение о внеочередном важном поезде и отправить ответ о готовности, вместо этого его автомат послал «я не сплю», тут все и поняли, что происходит. Выгнать его выгнали, но это не помешало ему стать известнейшим и уважаемым изобретателем.

                                                              Владимир, браво!
                                                              • 0
                                                                Мне нравится. Конструкция напомнило средневековое орудие пыток.
                                                                • 0
                                                                  А можно было бы сделать токен-генератор на андроиде и передавать в компьютер по bluetooth…

                                                                  Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.