李 順,肖龍遠(yuǎn)
(中國(guó)工程物理研究院電子工程研究所,四川綿陽(yáng),621900)
采用“用戶名+密碼”的原始模式進(jìn)行身份認(rèn)證已不再安全,為此提出了很多新的身份認(rèn)證技術(shù),如智能卡技術(shù)、生物識(shí)別技術(shù)。目前的智能卡已經(jīng)可以采用DES算法及基于RSA的PKI體系進(jìn)行認(rèn)證,也可以存儲(chǔ)和操作基于X.509的CA數(shù)字證書,但由于智能卡本身的硬件限制,使得進(jìn)行RSA運(yùn)算顯得非常緩慢,雖然有些智能卡附有協(xié)處理器加快了數(shù)學(xué)運(yùn)算,但增加了成本開銷。生物特征識(shí)別技術(shù)是利用人體生物特征來(lái)進(jìn)行身份驗(yàn)證的一種解決方案。指紋識(shí)別技術(shù)是眾多生物識(shí)別技術(shù)中最為實(shí)用和最為成熟的技術(shù)之一,指紋識(shí)別技術(shù)同智能卡,密碼等身份識(shí)別手段相比,具有不可替代、不可假冒、不易丟失等優(yōu)點(diǎn)[1]。本文將指紋識(shí)別技術(shù)應(yīng)用于嵌入式終端用戶身份認(rèn)證過(guò)程,有效解決了智能卡方案中認(rèn)證速度慢、密碼認(rèn)證方法安全性低的問(wèn)題。
AT91SAM9261是Atmel公司推出的基于ARM9的32位處理器。在工作頻率為180MHz的情況下,其運(yùn)算速度為200MIPS。其內(nèi)部支持LCD控制器、串行通信口(包括USB從機(jī)模塊、UART、SPI以及I2C)和多媒體通信口,還提供一個(gè)用于調(diào)試的JTAG接口。功耗方面,AT91SAM9261待機(jī)電流僅為2.5μA,工作頻率為 500Hz時(shí),電流消耗為 400μA。而且AT91SAM9261價(jià)格便宜,功耗低,又能滿足設(shè)計(jì)需要,所以AT91SAM9261非常適合用于嵌入式終端的開發(fā)。
采用艾菲爾公司的指紋模塊EFM-250,EFM-250是通用型指紋識(shí)別模塊,能完成指紋采集、指紋登記、指紋1:N和1:1比對(duì)等與指紋有關(guān)的操作。它由高速信號(hào)處理器DSP、射頻原理真皮指紋傳感器(滑動(dòng)式)、高性能指紋比對(duì)算法等軟硬件組成。EFM-250具有體積特別小,比對(duì)速度更快,指紋容量更大等特點(diǎn)。
指紋模塊與開發(fā)板的接口是采用標(biāo)準(zhǔn)串行口進(jìn)行通信(USART),開發(fā)板通過(guò)串口向模塊發(fā)送數(shù)據(jù)包,數(shù)據(jù)包中包含著指紋模塊應(yīng)執(zhí)行的命令(如提取指紋、搜索指紋等)。主機(jī)發(fā)送的數(shù)據(jù)包必須嚴(yán)格按照l(shuí)表1,表2格式封裝:
表1 指令包格式
表2 應(yīng)答包格式
系統(tǒng)主要由AT91SAM9261芯片、指紋傳感器、指紋信息處理器、存儲(chǔ)芯片、電源模塊、顯示模塊以及相應(yīng)的接口電路組成。使用16位的高性能SDRAM加快了數(shù)據(jù)的讀取速度,使用16M nand flash存儲(chǔ)嵌入式Linux操作系統(tǒng)。
圖1 系統(tǒng)硬件構(gòu)成
軟件開發(fā)主要是基于嵌入式Linux操作系統(tǒng)串口的讀寫操作以及根據(jù)通信協(xié)議開發(fā)板與指紋模塊進(jìn)行通信。由于身份認(rèn)證系統(tǒng)中若有些操作(如設(shè)置超級(jí)用戶密碼)出錯(cuò),將會(huì)影響以后的通信,這就需要通信過(guò)程中盡量避免出現(xiàn)收包出錯(cuò)的現(xiàn)象。本文采取了良好的出錯(cuò)處理機(jī)制,并利用select函數(shù)防止串口阻塞,提高了代碼的魯棒性和健壯性[2]。
串行口是計(jì)算機(jī)的一種常用接口,具有連接線少,通訊簡(jiǎn)單,得到廣泛使用。Linux中,串口COM1和COM2分別對(duì)應(yīng)操作系統(tǒng)的/dev/ttyS0,/dev/ttyS1兩個(gè)設(shè)備文件。Linux對(duì)設(shè)備的訪問(wèn)是通過(guò)設(shè)備文件的訪問(wèn)來(lái)進(jìn)行的,對(duì)串口的讀寫就相當(dāng)于對(duì)文件的讀寫[5]。
5.1.1 打開串口
fd=open(“/dev/ttyS1”,O_RDWR);//設(shè)置成可讀可寫,默認(rèn)阻塞模式
5.1.2 設(shè)置串口屬性
串口的屬性定義在結(jié)構(gòu)體struct termios中。為在程序中使用該結(jié)構(gòu)體,需要包含文件<termios.h>,該結(jié)構(gòu)體定義如下:
struct termios
{
tcflag_t c_iflag;/*輸入選項(xiàng)標(biāo)志*/
tcflag_t c_oflag;/*輸出選項(xiàng)標(biāo)志*/
tcflag_t c_cflag;/*控制選項(xiàng)標(biāo)志*/
tcflag_t c_lflag;/*本地選項(xiàng)標(biāo)志*/
cc_t c_line;/*line discipline*/
cc_t c_cc[NCCS];/* control characters*/
speed_t c_ispeed;/* input speed*/
speed_t c_ospeed;/* output speed*/
};
在這個(gè)結(jié)構(gòu)中最為重要的是c_cflag,通過(guò)對(duì)它的復(fù)制可以設(shè)置波特率、字符大小、數(shù)據(jù)位、校驗(yàn)位、停止位,流控協(xié)議等。輸入模式c_iflag成員控制端口接收端的字符輸入處理。c_cc包含了超時(shí)參數(shù)和控制字符的定義。
設(shè)置串口流程:
(1)保存原先的串口配置:這里可以使用函數(shù)tcgetattr(fd,&oldtio),這個(gè)函數(shù)得到與fd指向?qū)ο蟮南嚓P(guān)參數(shù),并將它們保存于oldtio引用的termios結(jié)構(gòu)中;
(2)激活選項(xiàng)CLOCAL和CREAD:CLOCAL和CREAD分別用于本地連接和接收使能,通過(guò)位掩碼的方式激活這兩個(gè)選項(xiàng);
(3)設(shè)置波特率:設(shè)置波特率有專門的函數(shù)cfsetispeed和cfsetospeed;
(4)設(shè)置字符大小:首先去除數(shù)據(jù)位中的位掩碼,再重新按要求設(shè)置;
(5)設(shè)置奇偶校驗(yàn)位:這時(shí)需要用到兩個(gè)termios中的成員:c_cflag和c_iflag。首先要激活c_cflag中的校驗(yàn)位使能標(biāo)志PARENB和是否要進(jìn)行校驗(yàn),同時(shí)還要激活c_iflag中的奇偶校驗(yàn)使能;
(6)設(shè)置停止位:設(shè)置停止位是通過(guò)激活c_cflag中的CSTOPB而實(shí)現(xiàn)的,若停止位為1,則清除CSTOPB,若停止位為2,則激活CSTOPB;
(7)設(shè)置最少字符和等待時(shí)間:分別通過(guò)設(shè)置c_cc[VMIN]和 c_cc[VTIME]來(lái)完成
(8)處理要寫入的引用對(duì)象:由于串口在重新設(shè)置之后,要寫入的引用對(duì)象要重新處理,調(diào)用函數(shù)tcflush(fd,TCIOFLUSH);
(9)激活配置:在完成全部串口配置之后,利用函數(shù)tcsetattr激活配置;
5.1.3 串口讀寫
可用標(biāo)準(zhǔn)的文件讀寫函數(shù):
ssize_t read(int fd,const void*buf,size_t count);//如果調(diào)用成功則返回讀出的字節(jié)數(shù)
ssize_t write(int fd,const void*buf,size_t count);//如果調(diào)用成功則返回寫入的字節(jié)數(shù)
在對(duì)串口進(jìn)行讀的時(shí)候,如果因?yàn)閿?shù)據(jù)傳輸出錯(cuò)導(dǎo)致讀不到數(shù)據(jù),此時(shí)read會(huì)阻塞,這時(shí)候程序?qū)?huì)死機(jī),解決這個(gè)問(wèn)題的方法是使用select函數(shù)實(shí)現(xiàn)串口的非阻塞讀寫:
struct timeval tv;//定義select阻塞的時(shí)間
fd_set readfd;//定義文件描述符集合
tv.tv_sec=maxwaittime/1000;//SECOND
tv.tv_usec=maxwaittime%1000*1000;//USECOND
FD_SET(fd,&readfd);
rc=select(fd+1,&readfd,NULL,NULL,&tv);
為了便于與指紋模塊通信,定義了結(jié)構(gòu)package_struct,直接通過(guò)package_read和package_send函數(shù)來(lái)實(shí)現(xiàn)對(duì)串口的發(fā)包、收包、解包的工作,兩個(gè)函數(shù)定義如下:
int SendPackage(package_struct package_send);
int ReceivePackage(package_struct*package_receive,unsigned short package_len);
身份認(rèn)證系統(tǒng)實(shí)現(xiàn)的功能有:
(1)設(shè)置超級(jí)用戶口令,用戶需要先驗(yàn)證超級(jí)用戶口令才能進(jìn)行其他操作,該口令默認(rèn)為0;
(2)自動(dòng)登記新指紋,自動(dòng)搜索指紋庫(kù)中的空位,提取指紋特征,進(jìn)行存儲(chǔ);
(3)自動(dòng)識(shí)別指紋,提取指紋特征,搜索指紋庫(kù),搜索到返回指紋的ID號(hào)及指紋匹配分?jǐn)?shù);
(4)清空指紋庫(kù),清空指紋庫(kù)中所有的指紋特征;
(5)刪除某個(gè)或多個(gè)指紋,刪除指紋庫(kù)中指定ID號(hào)開始的N個(gè)指紋特征;
(6)手動(dòng)登記,手動(dòng)識(shí)別,,這兩個(gè)功能需要多次發(fā)送指令包和接收解析包。手動(dòng)登記需要用戶指定指紋特征的存儲(chǔ)位置,操作較繁瑣,圖1中沒(méi)有給出兩者的實(shí)現(xiàn)流程;
軟件流程圖如圖2所示。
采用指紋識(shí)別技術(shù)對(duì)嵌入式終端用戶進(jìn)行身份認(rèn)證,詳細(xì)介紹了Linux中串口應(yīng)用的開發(fā),根據(jù)efm250的通信協(xié)議利用串口與指紋模塊進(jìn)行交互,在基于AT91SAM9261的開發(fā)板上實(shí)現(xiàn)了身份認(rèn)證系統(tǒng)的各種功能。經(jīng)過(guò)測(cè)試,該系統(tǒng)認(rèn)證速度快、可靠性高。
圖2 軟件流程圖
[1]柴曉光,岑寶熾.民用指紋識(shí)別技術(shù)[M].北京:人民郵電出版社,2004.
[2]冉林倉(cāng).Red Hat Linux 9編程開發(fā)與網(wǎng)絡(luò)管理[M].北京:電子工業(yè)出版社,2006.
[3]Greg Hankins.Linux Serial HOWTO v1.11[DB/OL].http://www.chinalinuxpub.com/.
[4]馬忠梅.ARM&Linux嵌入式教程[M].北京:北京航空航天大學(xué)出版社,2004.
[5]Kurt Wall.GNU/Linux編程指南(第二版)[M].張輝,譯.北京:清華大學(xué)出版社,2006.
[6]Sweet MR.Serial Programming Guide for POSIX Operating Systems[M].O’Reily& Associations,2002.