在Delphi中進行指紋儀的二次開發
一.指紋儀簡介
指紋具有"物證之首"的美譽。科學界對指紋的論點是:假設地球上有50億人口, 經過300年才會有兩個相同的指紋出現。可見,指紋的唯一性是具有無可辯駁的地位。
指紋儀第一次改變了我們熟知的數位化安全系統。此前,一切都依賴密碼。你必須用自己的用戶名,並且對你的系統進行設定。你必須遮住鍵盤以免其它人看見你的密碼。然而稍有疏忽的話,任何人都很能輕易竊取你的密碼。
有關專家預測:"透過指紋識別系統,我們擴展了家庭和商業電腦使用者在安全性方面的需求,不久的將來,無論是在區域網路還是在Internet,無論是註冊登入還是存取安全性數據,都將不再需要密碼,這一切只需要你用手指頭觸摸一下".
二.指紋儀的二次開發簡介
目前世界上的指紋儀廠商很多,影響力較大,被採用較多的當數DigitalPersona公司的U.are.U系列,DigitalPersona公司是全球最大電腦鍵盤製造商,這家公司使用的生物工程安全系統已經被Chicony Electronics列入協議中.這個協議是關於在鍵盤中集成DigitalPersona公司U.are.U指紋感應安全系統,這是為HP、Compaq和IBM等廠商製造的.
本文介紹的指紋儀二次開發就是以DigitalPersona公司的U.are.U 2000為原型的,U.are.U為you are you ,(你就是你)的縮寫. U.are.U 2000 微型指紋採集器能夠自動讀取指紋影像,並透過USB介面把數位化的指紋影像傳送到電腦。對於需要進行身份驗證的膝上型電腦、桌上型電腦或其他的個人電腦裝置,它是最理想的配件。
U.are.U 2000 是一款低成本的緊湊的指紋採集器。整合了精密光學系統、LED光源和CMOS攝影機協同工作,在影像攝取時進行電壓控制、自動矯正,並使用即插即用的USB介面.U.are.U 2000 指紋掃採集設計了通往DigitalPersona的U.are.U 指紋辨識演算法、應用程式和DigitalPersona通用驗證管理器(Universal Authentication Manager -UAM) 的介面--這些指紋相關的應用程式包括Windows登入、螢幕鎖定、口令替換及其加密磁碟機。
在購買指紋儀硬體產品的同時,商家一般都會附上硬體驅動程序,產品說明書,二次開發包及開發程序範例。透過軟體開發套件(SDK),可以在應用程式中增加指紋辨識的功能。
三.指紋儀二次開發過程中的關鍵技術
1.dll的調用
首先介紹一下在delpi中呼叫指紋儀開發包中的dll的方法。把開發包中的uruShell.dll放到程式目錄下或System目錄下。為了清晰明了起見,將DLL的呼叫宣告集中在一個程式單元Shelluru.pas中,在裡面把uruShell.dll 的函式匯出並作有關的參考聲明,具體源碼如下:
unit Shelluru;
interface
uses windows, Messages;
const
FT_OK = 0; // 成功
FT_ERR_NO_INIT = -1; // 沒有初始化
FT_ERR_UNKNOWN_DEVICE = -10; // 未知設備
FT_ERR_DEVICE_CONNECTED = -18; // 裝置已連接
FT_ERR_NO_DEVICE_CONNECTED = -19; // 無裝置可連接
MAX_REGISTER_COUNT= 8; // 最大可註冊數
ERR_REGISTER_FAIL= -110; // 註冊失敗
ERR_VERIFY_FAIL= -111; // 驗證失敗
ERR_REGISTER_COUNT= -112; // 註冊數
{ 以下是自訂訊息,MSG_FINGER_CAPTURED指紋取得訊息;}MSG_WAITING_FOR_IMAGE指紋等待訊息。
MSG_FINGER_CAPTURED= WM_USER + 80;
MSG_WAITING_FOR_IMAGE= WM_USER + 81;
type
PRegisterPixels = ^TRegisterPixels;
TRegisterPixels = array[1..MAX_REGISTER_COUNT] of Pointer;
///uru_Init初始化指紋儀,參數:numOfDev傳回電腦連線的指紋儀數量;FeatureLen傳回指紋資料長度。
function uru_Init(var numOfDev, FeatureLen: integer): integer; stdcall;
///uru_Connect連接特定指紋儀。參數:DeviceNo指紋儀號碼。
function uru_Connect(DeviceNo: integer): integer; stdcall;
///uru_Terminate斷開與指紋儀的連線。參數:DeviceNo指紋儀號碼。
procedure uru_Terminate(DeviceNo: integer); stdcall;
///uru_AllocFeature分配指紋資料位址。參數:Feature回傳的地址指針。
procedure uru_AllocFeature(var Feature: pointer); stdcall;
///uru_FreeFeature釋放已指派的位址。參數:Feature回傳的地址指針。
procedure uru_FreeFeature(var Feature: pointer); stdcall;
///uru_GetImageWidth取得指紋影像寬度。
function uru_GetImageWidth: integer; stdcall;
///uru_GetImageHeight取得指紋影像高度。
function uru_GetImageHeight: integer; stdcall;
///uru_Register指紋註冊函數。參數:hwnd視窗句柄,用於訊息傳送;DevieceNo指紋儀號碼;
///fngCount指紋登記次數;Pixels指紋影像連接指針;Features指紋註冊資料指針.
function uru_Register(hwnd: HWND; DeviceNo, fngCount: integer;Pixels: PRegisterPixels; Features: pointer): integer; stdcall;
///uru_AcquireFeatures指紋驗證函式。參數:hwnd視窗句柄,用於訊息傳送;DevieceNo指紋儀號碼.
function uru_AcquireFeatures(hwnd: HWND; DeviceNo: integer; Pixels, Features: pointer): integer; stdcall;
///uru_verifyFeatures指紋對比函數。參數:srcFeatures需要對比指紋資料;dstFeatures對比的指紋資料。
function uru_verifyFeatures(srcFeatures, dstFeatures: pointer): Boolean; stdcall;
///dll註冊函數
procedure uru_DllRegister; stdcall;
///中斷特定指紋儀取像函數。參數:DeviceNo指紋儀號碼。
Procedure uru_StopGetImage(DeviceNO:Integer);Stdcall;
implementation
const
DLLNAME= 'uruShell.dll';
{以下為呼叫uruShell.dll 導出函數的聲明}
function uru_Init; external DLLNAME;
function uru_Connect; external DLLNAME;
procedure uru_Terminate; external DLLNAME;
procedure uru_AllocFeature; external DLLNAME;
procedure uru_FreeFeature; external DLLNAME;
function uru_GetImageWidth; external DLLNAME;
function uru_GetImageHeight; external DLLNAME;
function uru_Register; external DLLNAME;
function uru_AcquireFeatures; external DLLNAME;
function uru_verifyFeatures; external DLLNAME;
procedure uru_DllRegister; external DLLNAME;
Procedure uru_StopGetImage;external DLLNAME;
end.
完成以上工作以後,則可以在主工程文件中引用Shelluru.pas文件,然後就可以呼叫Shelluru.pas文件中定義的函數了。
2.把驗證後的指紋資料保存在檔案或資料庫中
透過呼叫以上定義的函數,我們可以實現一個指紋的註冊,驗證,指紋資料保存,指紋再驗證(識別)的指紋辨識系統。以下重點介紹指紋的註冊和驗證辨識過程的程式實作:
procedure TForm1.BtnRegisterClick(Sender: TObject); file://註冊指紋
var
i:integer;
begin
if UserList.Selected = nil then
begin
MessageBox(application.Handle, '請先選擇使用者!', nil, MB_OK);
Exit;
end;
if UserList.Selected.Data <> nil then
Feature := UserList.Selected.Data file://此時Feature為空
else
uru_AllocFeature(Feature);
if Feature = nil then file://假如指紋特徵為空
begin
Status.SimpleText := '不能分配Feature記憶體';
Exit;
end;
for i := 1 to 4 do
begin
FillChar(Pixels[i]^, uru_GetImageWidth * uru_GetImageHeight, $FF);
Images[i].Refresh;
end;
Status.SimpleText := '開始註冊' + UserList.Selected.Caption + ' 的指紋...';
if uru_Register(Handle, DeviceNo, 4, @Pixels, Feature) = FT_OK then
begin
Status.SimpleText := UserList.Selected.Caption + ': 註冊成功!';
if UserList.Selected.Data = nil then
UserList.Selected.Data := Feature;
end
else
begin
if UserList.Selected.Data = nil then uru_FreeFeature(Feature);
Status.SimpleText := UserList.Selected.Caption + ': 註冊失敗!';
end;
end;
此函數主要呼叫了DLL中的uru_Register函數,用來為用戶註冊指紋,註冊指紋是為了提取指紋的特徵值,為特徵值分配一端內存,用來存儲指紋特徵值數據,並用一個指針指向這段內存,以便將來可以找回來。註冊完成後要立即進行一次驗證,確保資料無誤,驗證流程如下:
procedure TForm1.BtnVerifyClick(Sender: TObject); file://驗證指紋
var
aFeature:pointer;
i: integer;
fingerpath: string ;
begin
fingerpath:='C:/finger'+Edit9.Text+Edit10.Text;//指紋資料儲存路徑
if UserList.Selected = nil then
begin
MessageBox(Application.Handle, '請先選擇使用者!', nil, MB_OK);
Exit;
end;
if UserList.Selected.Data = nil then
begin
MessageBox(Application.Handle, PChar(Format('用戶%s 還沒有註冊指紋,請先註冊!', [UserList.Selected.Caption])), nil, MB_OK);
Exit;
end;
FillChar(Pixels[5]^, uru_GetImageWidth * uru_GetImageHeight, $FF);
Images[5].Refresh;
Status.SimpleText := '開始驗證' + UserList.Selected.Caption + ' 的指紋...';
Feature := UserList.Selected.Data; file://需要比較指紋數據
move(Feature^,byt,len); file://把記憶體中的一段長為len,從Feature開始的資料移到byte數組中
uru_AllocFeature(aFeature);//分配指紋資料位址
if (uru_AcquireFeatures(handle, DeviceNo, Pixels[5], aFeature) = FT_OK) and uru_verifyFeatures(@byt, aFeature) then
file://uru_AcquireFeatures指紋驗證
file://uru_verifyFeatures指紋對比
begin
Status.SimpleText := UserList.Selected.Caption + ': 驗證成功!';
AssignFile(F,fingerpath);//分配文件
ReWrite(F);//重寫文件
for i:=0 to len do
Write(F,byt[i]);//把指紋儀資料寫入文件
CloseFile(F);//關閉文件
end
else
Status.SimpleText := UserList.Selected.Caption + ': 驗證失敗!';
uru_FreeFeature(aFeature); file://釋放內存
end;
以上過程關鍵在於指紋驗證成功後,及時把記憶體中的指紋資料存到資料檔案中,資料檔案名稱最好是使用者名稱加上編號,以便日後驗證時方便找到對應的使用者指紋資料。最後還要記得把暫時分配的記憶體釋放掉。把指紋資料儲存到文件,以後就可以透過開啟檔案的方式,把資料檔案調出來,與目前使用者進行一個相符的過程,以便驗證使用者的正確身份,具體過程如下:
procedure TForm1.BitBtn2Click(Sender: TObject); file://驗證舊使用者指紋
var
aFeature1: pointer;
i: integer;
begin
if OpenDialog1.Execute then
begin
AssignFile(G,OpenDialog1.FileName);//指定文件
Reset(G);//重置文件
for i:=0 to len do
Read(G,byt2[i]);//把檔案中的指紋儀資料移到byte2數組中
CloseFile(G);//關閉文件
end;
FillChar(Pixels[5]^, uru_GetImageWidth * uru_GetImageHeight, $FF);
Images[5].Refresh;
Status.SimpleText := '開始驗證' + UserList.Selected.Caption + ' 的指紋...';
uru_AllocFeature(aFeature1);//分配指紋資料位址
if (uru_AcquireFeatures(handle, DeviceNo, Pixels[5], aFeature1) = FT_OK) and uru_verifyFeatures(@byt2, aFeature1) then
Status.SimpleText := UserList.Selected.Caption + ': 驗證成功!'
else
Status.SimpleText := UserList.Selected.Caption + ': 驗證失敗!';
uru_FreeFeature(aFeature1); file://釋放內存
end;
其實指紋數據也可以儲存在資料庫,這樣就可以實現多層結構系統,在伺服器上的資料庫集中訪問指紋數據,客戶端根據需要把註冊數據上傳伺服器,或在需要驗證舊用戶時從伺服器讀取數據,保證了安全性。
四.小結
本文介紹了利用U.are.U 2000指紋儀的開發包進行二次開發,實現一個指紋資料註冊,驗證,資料儲存和舊指紋再驗證的過程,這個過程可用在一些需要透過指紋辨識個人身分的系統中,筆者就是在這個基礎上開發了一個作為公安機構或住宅小區的暫住證管理系統的原型,主要實現住戶的暫住證管理功能.本文只介紹了對指紋儀開發包中的DLL的調用的方法以及二次開發中的註冊和驗證這些關鍵過程,至於指紋設備的連接,初始化,指紋圖象的顯示等因為比較簡單,所以沒有做深入的探討,讀者可以依照dll提供的函數自行開發。歡迎來信與我討論,我的email是[email protected]