Содержание


Обзор библиотеки libfprint, предназначенной для работы со сканерами отпечатков пальцев

Comments

Краткое описание библиотеки

Как вы уже поняли, libfprint – это библиотека с открытым исходным кодом работающая со специальными сканерами и поддерживающая аутентификацию пользователя по отпечатку пальца.

Изначально она создавалась в университете города Манчестер и была просто академическим проектом, нацеленным на упрощение для разработчиков процесса добавления поддержки различных популярных сканеров отпечатков пальцев.

Библиотека написана на языке С и лицензирована по LGPL-2. Разрабатывается она под операционную систему GNU/Linux, но должна быть легко переносима на другие операционные системы. Библиотека не требует каких-либо особых модулей ядра для работы со сканерами отпечатков пальцев – все драйверы функционируют в пространстве пользователя, и для доступа к устройствам предусмотрен единый API. Также libfprint поддерживает получение изображений сканируемого отпечатка в реальном времени, но для устройств, обрабатывающих изображение аппаратно, подобная возможность отсутствует.

Список поддерживаемых устройств довольно обширен и в основном включает сканеры, встраиваемые в ноутбуки (ASUS, HP, IBM, Lenovo и т.п.) или клавиатуры (DigitalPersona, Microsoft). Представлены и сканеры отпечатков пальцев в виде отдельных устройств, например такие как U.are.U 4000 Reader от DigitalPersona или 5thSense от Veridicom.

Возможности libfprint

Библиотека позволяет проводить процедуры так называемой идентификации и верификации пользователя. Естественно, перед этими процедурами необходимо выполнить сканирование отпечатка пальца и сохранение его в служебном каталоге библиотеки (~/.fprint) как эталонного. В зависимости от особенностей устройства, процесс может проводиться в один или несколько этапов.

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

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

Идентификация – это процесс сопоставления нового отпечатка пальца с коллекцией ранее сохраненных отпечатков. Например, человек, сканировавший свой отпечаток, идентифицируется в системе как пользователь номер N. Для продолжения регистрации в системе пользователь должен ввести пароль.

Иными словами, «верификация» производит сопоставление отпечатка пальца с одним ранее сохраненным отпечатком. При этом идентификатор пользователя, желающего войти в систему, заранее известен, и мы лишь подтверждаем, что «пользователь N» это именно «пользователь N», а не кто-то другой. При «идентификации» мы сравниваем отпечаток пальца со множеством других, ранее сохраненных, и таким образом узнаем идентификатор пользователя, т.е. получаем подтверждение, что неизвестный человек, приложивший палец к сканеру, является «пользователем N».

Работа с несовместимыми между собой устройствами

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

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

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

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

Инициализация библиотеки. Начало работы с предпочитаемым сканером

Перед использованием любых функций библиотеки libfprint необходимо подключить заголовочный файл libfprint/fprint.h, а также инициализировать библиотеку с помощью функции int fp_init(void), которая возвращает 0 в случае успеха.

После завершения использования любых функций библиотеки необходимо вызвать функцию void fp_exit(void), освобождающую ресурсы библиотеки. После вызова этой функции дальнейшая работа с библиотекой невозможна до тех пор, пока вы снова не инициализируете ее при помощи функции fp_init()!

Перед сканированием отпечатка пальца нам необходимо выбрать устройство, которое будет использовано. Следует помнить, что устройств в системе может быть несколько. Получить указатель на список устройств можно при помощи функции struct fp_dscv_dev ** fp_discover_devs(void). После использования списка занимаемую им память необходимо освободить, что делает функция void fp_dscv_devs_free(struct fp_dscv_dev ** devs), которая принимает единственный параметр – указатель на список устройств.

Выбранное устройство требуется инициализировать перед использованием. Эта процедура выполняется функцией struct fp_dev * fp_dev_open(struct fp_dscv_dev * ddev), которой передается указатель на устройство. Возвращаемое значение – указатель на открытое устройство или NULL в случае ошибки. После успешной инициализации можно приступать непосредственно к сканированию отпечатка пальца.

В конце работы программы необходимо закрыть используемое устройство. Делается это функцией void fp_dev_close(struct fp_dev * dev), которой передается указатель на устройство, возвращенный прежде функцией fp_dev_open(). Если передать в функцию NULL, то она сразу же вернет управление в точку вызова.

Обзор средств, обеспечивающих сканирование отпечатка пальца и сохранение его на диск

В зависимости от особенностей устройства, для завершения сканирования может потребоваться не один раз провести пальцем по сканеру. Количество необходимых считываний пальца возвращается функцией int fp_dev_get_nr_enroll_stages(struct fp_dev * dev), в качестве единственного параметра которой мы передаем указатель на открытое нами устройство.

Непосредственно считывание пальца выполняется функцией int fp_enroll_finger_img(struct fp_dev * dev, struct fp_print_data ** print_data, struct fp_img ** img). Передаваемые параметры: dev – устройство, используемое для проведения сканирования; print_data – указатель на конечный результат процесса сканирования, который должен быть освобожден после использования при помощи функции void fp_print_data_free(struct fp_print_data * data); img – указатель на сканированное изображение. Можно передать NULL, если изображение не требуется. После использования изображения ресурсы должны быть освобождены функцией void fp_img_free(struct fp_img * img).

Для функции fp_enroll_finger_img() есть функция «обертка» int fp_enroll_finger(struct fp_dev * dev, struct fp_print_data ** print_data), не сохраняющая изображение. Два ее параметра аналогичны соответствующим параметрам функции fp_enroll_finger_img().

При успешном завершении очередного этапа сканирования описанными выше функциями возвращается fp_enroll_result::FP_ENROLL_PASS; при успешном завершении всего процесса сканирования функции вернут fp_enroll_result::FP_ENROLL_COMPLETE. При проверке кодов возврата этих функций следует помнить, что код ошибки можно получить не только из-за программной или аппаратной проблемы, но и в случае ошибки пользователя: человек слишком быстро двигал пальцем по сканеру, не приложил палец к сканеру и т.д. В этих случаях необходимо вновь вызвать функцию fp_enroll_finger_img() или fp_enroll_finger(), чтобы продолжить процесс сканирования отпечатка пальца.

Сохранение полученного отпечатка пальца в служебном каталоге библиотеки производится функцией int fp_print_data_save(struct fp_print_data * data, enum fp_finger finger). Первым параметром она принимает указатель на конечный результат процесса сканирования, а вторым – номер пальца, который был использован при сканировании. Функция возвращает 0 при успешном завершении операции сохранения отпечатка.

Номера человеческих пальцев определены в перечислении fp_finger следующим образом:

LEFT_THUMB – большой палец левой руки;

LEFT_INDEX – указательный палец левой руки;

LEFT_MIDDLE – средний палец левой руки;

LEFT_RING – безымянный палец левой руки;

LEFT_LITTLE – мизинец левой руки;

RIGHT_THUMB – большой палец правой руки;

RIGHT_INDEX – указательный палец правой руки;

RIGHT_MIDDLE – средний палец правой руки;

RIGHT_RING – безымянный палец правой руки;

RIGHT_LITTLE – мизинец правой руки.

Сканируем отпечаток пальца и сохраняем его на диск

Исходный код рассмотренных в статье программ вы сможете загрузить по ссылке в конце статьи. Сборка производится командой: gcc filename.c -lc -lfprint. Для успешной компиляции программ необходима сама библиотека libfprint и ее заголовочные файлы.

Рассматриваемая в этом разделе программа использует первый найденный сканер отпечатков пальцев. Полученный отпечаток сохраняется в служебном каталоге библиотеки; если сканер может передавать изображение отпечатка, то это изображение сохраняется в файл enrolled.pgm. Последняя операция выполняется функцией int fp_img_save_to_file(struct fp_img * img, char * path), первый параметр которой – указатель на структуру, возвращенную функцией fp_enroll_finger_img(), а второй параметр – путь к файлу с изображением (в формате PGM). В случае успеха функция возвращает 0.

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

switch (enroll_retval) { 
	case FP_ENROLL_COMPLETE: 
		printf("Enroll complete!\n"); 
		break; 
	case FP_ENROLL_PASS: 
		printf("Enroll stage passed.\n"); 
		break; 
	case FP_ENROLL_RETRY: 
		printf("Didn't quite catch that. Please try again.\n"); 
		break; 
	case FP_ENROLL_RETRY_TOO_SHORT: 
		printf("Your swipe was too short, please try again.\n"); 
		break; 
	case FP_ENROLL_RETRY_CENTER_FINGER: 
		printf("Didn't catch that, please center your finger on the\ 
sensor and try again.\n"); 
		break; 
	case FP_ENROLL_RETRY_REMOVE_FINGER: 
		printf("Scan failed, please remove your finger and then try\ 
again.\n"); 
		break; 
	case FP_ENROLL_FAIL: 
		printf("Enroll failed, something wen't wrong :(\n"); 
		fp_dev_close(dev); 
		fp_exit(); 
		return 1; 
} /* switch (enroll_retval) */

К сожалению, приходится использовать эту конструкцию, так как в библиотеке отсутствует функция, переводящая численные коды ошибок, возвращаемые функциями библиотеки, в эквивалентные текстовые описания (что-нибудь наподобие strerror()).

Обзор средств, обеспечивающих верификацию пользователя по отпечатку пальца

Верификация пользователя обеспечивается при помощи функции int fp_verify_finger_img(struct fp_dev * dev, struct fp_print_data * enrolled_print, struct fp_img ** img). Первым параметром в нее передается устройство, используемое для сканирования пальца; вторым параметром – указатель на уже эталонный отпечаток. Третий параметр – указатель на изображение сканированного пальца – можно передать NULL, если изображение не требуется.

Можно использовать функцию fp_verify_finger() – обертку вокруг fp_verify_finger_img(). Она принимает только два параметра: устройство, используемое для сканирования и указатель на эталонный отпечаток. Указатель на изображение сканированного пальца принимается равным NULL.

Обе рассмотренные выше функции возвращают одно из значений, описанных в перечислении fp_verify_result. В случае несовпадения отпечатков возвращается fp_verify_result::FP_VERIFY_NO_MATCH. В случае совпадения – fp_verify_result::FP_VERIFY_MATCH. Остальные коды возврата, описанные в перечислении, соответствуют ошибкам пользователя (палец мог быть не отцентрирован на сканере, пользователь слишком быстро провел пальцем по сканеру и т.п.). В случае аппаратной или программной ошибки будет возвращено отрицательное число. Стоит отметить, что, как и для функции fp_enroll_finger_img(), пользовательские ошибки, полученные в функциях fp_verify_finger_img() и fp_verify_finger(), являются устранимыми, в отличие от программных и аппаратных проблем.

Программа, верифицирующая пользователя по ранее сохраненному отпечатку пальца

Поиск и открытие необходимого сканера отпечатков пальцев выполняется в нашей программе так же, как и в предыдущей – мы получаем список доступных устройств и инициализируем первое из них.

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

Загрузка отпечатка пальца производится функцией int fp_print_data_load(struct fp_dev * dev, enum fp_finger finger, struct fp_print_data ** data), которой в качестве параметров передаются: используемое устройство, необходимый программе палец и указатель на область данных, в которую запишется вся необходимая информация о запрошенном отпечатке. Функция вернет 0 в случае успешного завершения или -ENOENT в случае отсутствия запрашиваемого отпечатка и любое другое ненулевое значение в случае ошибки.

Затем мы сканируем отпечаток пальца и сверяем его с эталонным. Производится это при помощи функции fp_verify_finger() в цикле – до тех пор, пока пользователь не проведет пальцем по сканеру, соблюдая необходимую скорость и уровень нажима, и мы не получим годный для использования отпечаток.

Обработка ошибок выполняется так же, как в предыдущей программе, и выглядит следующим образом:

switch (verify_retval) { 
	case FP_VERIFY_NO_MATCH: 
		printf("NO MATCH!\n"); 
		break; 
	case FP_VERIFY_MATCH: 
		printf("MATCH!\n"); 
		break; 
	case FP_VERIFY_RETRY: 
		printf("Scan didn't quite work. Please try again.\n"); 
		break; 
	case FP_VERIFY_RETRY_TOO_SHORT: 
		printf("Swipe was too short, please try again.\n"); 
		break; 
	case FP_VERIFY_RETRY_CENTER_FINGER: 
		printf("Please center your finger on the sensor and try again.\n"); 
		break; 
	case FP_VERIFY_RETRY_REMOVE_FINGER: 
		printf("Please remove finger from the sensor and try again.\n"); 
		break; 
} /* switch (verify_retval) */

Остальные функции библиотеки libfprint

Для проведения операции по идентификации пользователя библиотека предоставляет функцию int fp_identify_finger_img(struct fp_dev * dev, struct fp_print_data ** print_gallery, size_t * match_offset, struct fp_img ** img). Параметр match_offset указывает на место, куда можно сохранить индекс совпавшего отпечатка пальца в галерее; этот параметр действителен только в том случае, если отпечаток пальца успешно идентифицирован. Параметр print_gallery – это массив указателей на отпечатки пальцев, оканчивающийся указателем на NULL; иными словами, это наша «галерея» эталонов. Остальные два параметра уже известны и были рассмотрены раньше для подобных функций. Возвращаемое значение будет одним из описанных в fp_verify_result. В случае аппаратной или программной ошибки возвращается отрицательное число.

У этой функции также есть функция-обёртка, подставляющая NULL вместо указателя img.

Если есть необходимость просто получить изображение отпечатка пальца без получения дополнительных данных о нем, наподобие print_data или проведения дополнительных действий наподобие верификации или идентификации, то стоит воспользоваться функцией int fp_dev_img_capture(struct fp_dev * dev, int unconditional, struct fp_img ** image). Назначение первого и последнего параметров очевидно – подобные были разобраны ранее; на втором следует остановиться подробнее. Параметр unconditional отвечает за способ захвата изображения со сканера, который может начать захватывать изображение немедленно, если параметр не равен 0. Также сканер может начать захват изображения сразу, как только палец будет обнаружен, в случае, если параметр равен нулю. Функция возвращает 0, если все прошло успешно, и ненулевое число в случае ошибки. Возвращение -ENOTSUP означает, что параметр unconditional был установлен, но устройство не поддерживает подобный режим работы, или устройство не может выполнить захват изображения.

Проверить поддержку устройством захвата изображения пальца можно функцией int fp_dev_supports_imaging(struct fp_dev * dev). Она возвращает не равное нулю число, если захват поддерживается.

Полученное функцией fp_dev_img_capture() изображение может представлять собой просто «сырые» данные, предоставленные сканером. В таком случае его необходимо «стандартизировать». За это отвечает функция void fp_img_standardize(struct fp_img * img). Она принимает указатель на изображение отпечатка пальца и производит коррекцию цвета, ориентации и т.п. Ссылка на «стандартизированное» изображение возвращается в том же указателе.

Заключение

Конечно, мы рассмотрели далеко не все возможности библиотеки (это сложно сделать в рамках одного материала). Но данная статья и не была задумана как исчерпывающее руководство. Скорее, это небольшая вводная инструкция, которая позволит читателю начать разработку программ, работающих со сканерами отпечатков пальцев, без длительного чтения документации. С оставшимися функциями можно ознакомиться по приведенным ниже ссылкам. Кроме того, если у читателей возникнет желание посмотреть на продукты, использующие libfprint, можем порекомендовать модуль pam_fprint, выполняющий аутентификацию пользователя в Linux при помощи этой библиотеки. Разумеется, не стоит забывать и о примерах, поставляемых с libfprint (их можно найти в каталоге examples/ дерева исходных текстов библиотеки).


Ресурсы для скачивания


Похожие темы


Комментарии

Войдите или зарегистрируйтесь для того чтобы оставлять комментарии или подписаться на них.

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=40
Zone=Linux
ArticleID=461629
ArticleTitle=Обзор библиотеки libfprint, предназначенной для работы со сканерами отпечатков пальцев
publish-date=01142010