一.指紋儀簡介
指紋具有"物證之首"的美譽。科學界對指紋的論斷是:假設地球上有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]