??? 摘? 要:介紹USB安全鑰的完整功能,加密算法的動態(tài)鏈接庫DLL設計,在線修改存儲在安全鑰內(nèi)的用戶產(chǎn)品信息功能的方法,。為設計完整的USB設備提供借鑒,。?
??? 關鍵詞:通用串行總線USB? 單片機? 動態(tài)鏈接庫DLL? 標準加密算法DES? USB固件? USB驅動程序? 人機接口設備HID?
?
1? USB安全鑰的完整功能?
??? USB安全鑰最早基于USB的熱插拔、速度以及硬件等優(yōu)勢,結合加密算法,用于辦公文件,、軟件等的存儲和加密,。但USB安全鑰的用武之地遠不止這些,與網(wǎng)絡技術結合,用于時下最時尚的電子商務中,才使其大顯神通,。USB安全鑰結合傳統(tǒng)的電子商務核心技術和新興的USB技術,用于實現(xiàn)電子商務中的關鍵技術——身份識別,在未來電子商務領域具有廣闊的應用前景,。USB安全鑰集數(shù)據(jù)加密和數(shù)據(jù)存儲兩大功能于一體,推動了電子商務的發(fā)展,。?
??? 傳統(tǒng)的電子商務或是網(wǎng)絡email等的身份認證基本上是通過兩種方式來實現(xiàn)的。一種是密碼機制,雙方約定好規(guī)則,。這是目前最為普遍的方式,但是這種方式的嚴重缺點顯而易見。密碼作為最重要的信息,在網(wǎng)絡上傳輸,很容易被黑客攻擊截獲,經(jīng)常發(fā)生密碼被盜,。第二種方式是通過第三方的認證,雙方共同信任第三方公司提供的信息,從而進行交易,。微軟在.NET計劃中推出的認證服務器就提供這種服務。但是,信譽度建立在第三方上,便會受到第三方的制約,掏錢不說,還要擔心第三方是否會倒閉,。USB安全鑰解決了這兩種方式無法解決的問題,。?
??? 完整的USB安全鑰系統(tǒng)由三部分組成:安全鑰端,采用Motorola公司帶USB接口的8位單片機MC68HC908JB8構成;PC端,由任何一臺可接入網(wǎng)絡的PC構成,并安裝PC端的用戶身份認證軟件;Server端,任何一臺網(wǎng)絡服務器安裝用于身份認證的Server端軟件。?
??? USB安全鑰系統(tǒng)結構體系及功能流程如圖1所示,列出了九個步驟,描述了USB安全鑰從插入PC到完成一次身份識別的完整流程,。?
?
?
??? 需要強調(diào)的是,在上述步驟中,PC僅僅起一個Media(媒介)的作用,。任何重要的數(shù)據(jù)都沒有經(jīng)過PC,在網(wǎng)絡上傳輸?shù)膬H僅是8個字節(jié)的隨機數(shù)(它只在Server服務器和安全鑰端有意義,只對特定的加密算法和密鑰有意義),被黑客截取也不會有問題。這8個字節(jié)的隨機數(shù)由網(wǎng)絡Server產(chǎn)生,經(jīng)由PC傳遞給USB安全鑰加密;加密后的隨機數(shù)再由PC不加任何改變地傳遞給Server;Server去調(diào)用解密算法解開加密的隨機數(shù),與原來未加密的隨機數(shù)比較,如果相同則說明USB安全鑰的持有者身份合理,。整個身份認證也告結束,。這里,USB安全鑰體現(xiàn)出兩大優(yōu)點:(1)沒有任何重要的個人信息在網(wǎng)上傳遞,保證了安全性;(2)Server由網(wǎng)絡商自己維護,安全鑰由用戶攜有,雙方的認證沒有依靠第三方,快捷、安全,、信譽度高,。當然,USB安全鑰還有其他很多優(yōu)點,例如可以在PC上熱插拔,可以在任何一臺支持USB的PC上工作(現(xiàn)在幾乎所有的PC都應該支持USB)等。?
2 USB安全鑰的技術細節(jié)?
??? USB安全鑰技術,從設計上可以分為三個模塊:Server端的網(wǎng)絡通訊和加密算法設計,、PC端的USB驅動程序和網(wǎng)絡通訊設計,、安全鑰端的USB固件和加密算法設計。涉及到的計算機技術包括Socket網(wǎng)絡編程技術,、USB驅動程序設計技術和加密算法技術,。可以說整個設計內(nèi)容龐雜,技術難度高,。因此,設計時就需細化,一步步完成單個功能,再進行聯(lián)調(diào),將單個模塊融合成完整的USB安全鑰,。?
??? 后期的功能擴展和優(yōu)化設計也是針對三個模塊,應用三大技術完成。主要是:服務器(Server)端DES加密算法的研究,設計加密算法的動態(tài)鏈接庫DLL,提供給客戶最簡單的API;PC和安全鑰端驅動程序的研究,實現(xiàn)PC端友好的程序界面,動態(tài)在線修改存儲在安全鑰內(nèi)的用戶產(chǎn)品信息,。本文將詳細介紹擴展和優(yōu)化的設計方法,從而揭示USB安全鑰的技術細節(jié),。?
2.1 如何設計Server端加密算法及其DLL?
??? 密碼算法(Algorithm)就是指加密函數(shù)(Encryption)和解密函數(shù)(Decryption),。有加密函數(shù),那么必然有一套與它對應的解密函數(shù)。現(xiàn)代密碼學用密鑰技術解決了保密性不夠的問題,。密鑰用K表示,。K的取值范圍叫做密鑰空間??梢杂萌缦率阶觼肀硎炯用芎徒饷芎瘮?shù)之間的關系:?
??? DK(EK(M))=M?
??? 其中,E為加密函數(shù),D為解密函數(shù),M為被加密的原文,。有一個重要的結論:所有算法的安全性都基于密鑰的安全性,而不是算法細節(jié)的安全性。這就是說,算法可以公開,只要密鑰是保密的,則這個算法就是安全的,。簡單地說,密鑰就是與密文疊加在一起的一組數(shù),。?
??? 標準加密算法DES作為ANSI的數(shù)據(jù)加密算法和ISO的DEA-1,成為世界范圍內(nèi)的標準已經(jīng)20多年。就目前密碼學的發(fā)展情況來說,DES的安全性還是能夠滿足用戶需求的,。由于完整的DES算法相當復雜,這里僅簡單介紹算法的結構,。?
??? DES是分組加密算法,以64位為一組對明文進行分組,然后進行加密和解密。加密和解密的算法相同,只是密鑰的編排不同,。密鑰長度為56位,通常是64位,但是每字節(jié)第8位都用來作為奇偶校驗位,因此實際上只有56位,。DES共有16輪,即對同一組明文結合密鑰進行16輪相同的加密過程,最終達到加密要求。?
??? 具體到每一輪的加密過程是這樣的:每一輪中,密鑰位移位,然后從密鑰中選出48位,。數(shù)據(jù)的32位右半部分數(shù)據(jù)擴展成48位,與密鑰結合,。然后再將這48位數(shù)據(jù)變換為32位,并與數(shù)據(jù)的32位左半部分相與后作為新的32位右半部分。而32位左半部分基本不變,。最后,左右各32位數(shù)組合在一起便構成了一輪加密后的64位密文,。重復同樣運算16次,便完成了加密/解密功能[4]。?
??? Server端的加密算法采用DES,。加密和解密是整個USB安全鑰身份認證的核心,。在安全鑰的初期產(chǎn)品中,已經(jīng)實現(xiàn)了DES算法下的加密功能。但是,作為產(chǎn)品,其安全性是第一位的,。而且,對于要將加密算法嵌入自己系統(tǒng)的用戶來說,提供給他們大量的加密算法的源代碼是不合適的,。要對DES算法進行修改,將其從Server端的源程序中提出,改掉原來復雜的調(diào)用機制,改為提供給用戶三個簡單的接口函數(shù):產(chǎn)生隨機數(shù)、加密和解密函數(shù),、實現(xiàn)DES加密算法的DLL,。?
??? 動態(tài)鏈接庫(DLL)是一個包含了若干個函數(shù)的可執(zhí)行模塊,Windows應用程序可以調(diào)用這些函數(shù)來完成實際任務。對于調(diào)用DLL的用戶來說,利用的資源僅僅是應用函數(shù)接口和一個后綴為.dll的文件,實現(xiàn)加密算法的模塊化,。?
??? 在建立了一個VC工程之后,需要建立主程序頭文件KeyDll.h,加入如下代碼,。這些代碼中定義了導出的四個函數(shù)。?
class _declspec(dllexport) CKeyDllApp?
{public:?
??? BOOL GetChallenge();?
??? int* Challenge();//導出函數(shù)?
??? int* DecryptData(BYTE []);//導出函數(shù),需要解密的隨機數(shù),可存儲在數(shù)組InputNum[8]中,。此函數(shù)輸出值即為加密后的數(shù)據(jù),輸出格式為數(shù)組DESDeData[8]?
??? int* EncryptData(BYTE []);//導出函數(shù),需要加密的隨機數(shù),可存儲在數(shù)組InputNum[8]中,。此函數(shù)輸出值即為加密后的數(shù)據(jù),輸出格式為數(shù)組DESEnData[8]?
??? BOOL cha_gen;?
??? void DESDecrypt ();//BYTE *Data, BYTE *Key);?//解密函數(shù)定義?
??? void DESEncrypt ();//BYTE *Data, BYTE *Key);?//加密函數(shù)定義?
??? BOOL Init();?
protected:?
??? BYTE DESKey[8]; ??? //密鑰?
??? BYTE IniDeData[8]; //外部輸入的需要解密的數(shù)據(jù)?
??? BYTE IniEnData[8]; //外部輸入的加密前的隨機數(shù)?
??? BYTE DESDeData[8]; //解密后的數(shù)據(jù)?
??? BYTE DESEnData[8]; //加密后的數(shù)據(jù)?
??? WORD subkey[16][48]; //子密鑰?
??? BYTE challenge[8];?
......}?
??? 然后,在主文件KeyDll.cpp中實現(xiàn)各功能函數(shù)的具體功能,主要是算法的實現(xiàn)。?
BOOL CKeyDllApp::GetChallenge()//這是產(chǎn)生隨機數(shù)的函數(shù),它調(diào)用API的函數(shù)srand(),最終產(chǎn)生的8位隨機數(shù)存在數(shù)組challenge[8]中?
{?
??? int i;?
??? srand((unsigned)time(NULL));?
??? if(!cha_gen){?
??? ??? for(i = 0; i < 8; i++){?
??? ??? do{challenge[i] = (rand()/256);}?
??? ??? while((challenge[i]=='t') || (challenge[i] == 0) || (challenge[i]==255) || (challenge[i]== 256- 't'));}?
??? ??? challenge[8] = 0;?
??? ??? cha_gen = TRUE;?
??? ??? return TRUE;}?
??? return FALSE;}?
?
void CKeyDllApp::DESDecrypt ()//解密函數(shù),完成對已加密的8位隨機數(shù)的解密功能 ?
{?
??? WORD TempInput[64],TempOutput[64],TempKey[64];?
??? stringtobit (IniDeData, TempInput);?
??? stringtobit (DESKey, TempKey);?
??? decry (TempInput, TempKey, TempOutput);?
??? bittostring (TempOutput, DESDeData);}?
?
void CKeyDllApp::DESEncrypt()?? //加密函數(shù),可完成?
對8位隨機數(shù)的加密功能,然后可與原隨機數(shù)比較,看是否相等?
{?
??? WORD TempInput[64], TempOutput[64],TempKey[64];?
??? stringtobit (IniEnData, TempInput);?
??? stringtobit (DESKey, TempKey);?
??? encry (TempInput, TempKey, TempOutput);?
??? bittostring (TempOutput, DESEnData);}?
?
int* CKeyDllApp::DecryptData(BYTE InputDeNum[8])//導出的獲取解密數(shù)據(jù)的函數(shù),。此函數(shù)需要賦值——已加密了的8位隨機數(shù),并進行解密,最終函數(shù)值為解密后的?
8位隨機數(shù)?
{?
??? int i;?
??? for (i = 0; i < 8; i++)?
??? IniDeData[i]=InputDeNum[8];?
??? return (int *)DESDeData;}?
?
int* CKeyDllApp::EncryptData(BYTE InputEnNum[8])//導出的獲取加密數(shù)據(jù)的函數(shù),。此函數(shù)需要賦值——8位隨機數(shù),直接調(diào)用并賦8位隨機數(shù)后,此函數(shù)將調(diào)用加密函數(shù)并進行加密,最終函數(shù)值為加密后的8位隨機數(shù)?
{?
??? int i;?
??? ??? for (i = 0; i < 8; i++)?
??? ??? IniEnData[i]=InputEnNum[i];?
??? ??? return (int *)DESEnData;} ?
?
??? 編譯,、連接后將產(chǎn)生一系列文件,在加上源工程文件,將會有數(shù)量比較龐大的文件系統(tǒng)。最終,只需提供給用戶三個文件即可,它們是:?
??? · KeyDllDebugKeyDll.dll,這是DLL文件;?
??? · KeyDllDebugKeyDll.lib,這個文件將在應用DLL的程序編譯和連接時,提供連接向導;?
??? · KeyDllKeyDll.h,這個頭文件告訴用戶此DLL中導出了哪些量可以用,。?
??? DES的DLL導出了一個類:CkeyDllApp,。在這個類中共有4個導出函數(shù)可以導入應用程序中,用戶在導入了加密DLL后,可以在自己的程序中直接調(diào)用以下函數(shù):?
??? · BOOL GetChallenge(),用于在應用程序支持循環(huán)結構;?
??? · int*Challenge(),產(chǎn)生隨機數(shù),并存儲在Challenge[8]中;?
??? · int*DecryptData(BYTE []),用于解密隨機數(shù);?
??? · int*EncryptData(BYTE []),用于加密隨機數(shù)。?
2.2 USB安全鑰新增功能描述?
??? USB安全鑰和PC傳輸?shù)臄?shù)據(jù)量不大,而且沒有很高的速度要求,。因此,在編寫固件時就將其歸類為HID(USB的人機接口設備類),。在編寫PC端的驅動程序時可以直接調(diào)用Windows提供的HID的API函數(shù),大大降低了編程的難度。更重要的是,Windows對HID設備的支持非常完備,不需要用戶再編寫底層的驅動,。?
??? 安全鑰端的設計內(nèi)容主要是:實現(xiàn)在線修改存儲在安全鑰內(nèi)的KeyID和讀取KeyID兩個功能,分別由函數(shù)Set_KeyID和Get_KeyID實現(xiàn),。KeyID是安全鑰的標識符,在安全鑰插到PC上后,被讀出并送往Server進行檢查。在初期產(chǎn)品中,KeyID只能是安全鑰首次接到PC上讀取,且不能更改,這為廠家和開發(fā)者造成了不便,。因此要更改初期產(chǎn)品中的KeyID,就必須修改安全鑰端的匯編程序,然后再“燒”寫到安全鑰中,非常麻煩,。新增功能可實現(xiàn)KeyID的在線修改。?
??? PC端的設計包括兩步,。首先要實現(xiàn)在PC上讀取安全鑰內(nèi)的KeyID,。通過安全鑰的端點1,8個字節(jié)的KeyID被周期地送出。PC要獲取這些數(shù)據(jù),調(diào)用HID類庫Get_Report(Feature),。從安全鑰發(fā)來的包含KeyID的包的特性及技術指標如表1,。?
?
?
??? 第2步,在PC上實現(xiàn)修改KeyID功能,。調(diào)用HID類庫Set_Report(Feature),將新的KeyID發(fā)送到安全鑰中,具體指標如表2所示,。
?
?
2.3 如何設計安全鑰端新增功能的USB固件?
??? USB固件(Firmware),就是USB安全鑰硬件上采用的單片機和其他處理器中有關USB通信的程序。這里采用Motorola公司的8位單片機MC68HC908JB8作為USB安全鑰的控制器芯片,。MC68HC908JB8帶有USB接口,8K的Flash,支持USB 1.1版本中的低速(Low Speed)設備,資源有限,主要用于實現(xiàn)USB通信,價格比較低廉,。因此,很適合于USB安全鑰。MC68HC908JB8中USB通信的程序模塊,包含在實現(xiàn)MC68HC908JB8所有功能的匯編程序中,。?
??? 圖2是經(jīng)典的USB固件的流程圖,。考慮到USB安全鑰中USB數(shù)據(jù)通信量很小,不需要考慮通信時間,采用中斷傳輸方式,。整個程序就是在等待數(shù)據(jù)傳輸要求的中斷到來,從而進入數(shù)據(jù)傳輸模塊,。讀/寫數(shù)據(jù)緩沖區(qū),往USB端點(Endpoint)中讀/寫數(shù)據(jù),交給USB模塊收發(fā)數(shù)據(jù)。當USB安全鑰不需要傳輸數(shù)據(jù)時,就進入掛起狀態(tài)(Suspend),。在得到PC主機遠程喚醒后啟動,繼續(xù)工作,。?
?
?
??? 新增功能中,主要完成的兩個功能就是KeyID的讀取和修改,即實現(xiàn)Get_KeyID和Set_KeyID功能。程序構思大致是:對于Get_KeyID,在接收到PC端發(fā)來的讀取KeyID的中斷后,立即從端點1發(fā)送8字節(jié)的KeyID,這一段沒有什么特別之處;對于Set_KeyID,在接收到信號后,立即轉入Set_KeyID子程序,。首先將存儲KeyID的Flash去保護,然后寄存器置位,即在硬件上給Flash一個高電平,接著進行擦除,再將保存于緩沖區(qū)的PC發(fā)來的新KeyID存儲到Flash中,。最后,置Flash狀態(tài)寄存器位,給Flash加保護。?
2.4 PC端新增功能的USB驅動程序設計?
??? Windows 98的驅動程序從結構上來說分為兩層:內(nèi)核層和用戶層,。USB的客戶驅動程序屬于用戶層,而USB類驅動程序和底層驅動程序則屬于內(nèi)核層,。目前,USB還屬于起步階段,Windows對USB的支持還不夠完善,僅支持內(nèi)核層,。USB開發(fā)人員所要做的,就是開發(fā)客戶驅動程序,直接與類驅動程序打交道。?
??? HID屬于USB設備類中的一個子類,Windows對它提供了非常強大的支持,尤其是在用戶層提供了Hid.dll,其中包含了用戶層驅動程序與類驅動程序通信需要的各種功能模塊,將它們以API的形式提供給用戶函數(shù)接口,。這樣,在編寫客戶驅動程序的時候就可以直接調(diào)用這些API函數(shù)來完成諸如IN,、OUT等功能,大大降低了編寫驅動程序的難度。?
??? HID客戶驅動程序訪問HID類驅動程序,由HID類驅動程序完成大多數(shù)工作,而硬件交互由HID小驅動程序HidUsb.sys處理,HID小驅動程序調(diào)用USB底層驅動程序USBD.sys訪問設備,。?
??? 這里介紹用戶模式的HID客戶驅動程序設計過程,。它主要包括三個方面的工作:?
??? ·查找所有HID設備;?
??? ·對于查找到的每一個HID設備,檢查其功能,判斷是否為感興趣的設備;?
??? ·根據(jù)用戶需要讀取HID輸入Report(Feature)或者寫HID輸出Report(Feature)。?
??? 程序流程如下:?
??? (1)查找USB安全鑰設備;?
??? (2)讀取HID設備功能;?
??? (3)具體實現(xiàn)Get_KeyID和Set_KeyID子函數(shù);?
BOOL??? CUsbKey::GetKeyID()? //Get_KeyID子程序?
{...?
??? result=HidD_GetFeature(HidDevice, ReadBuffer,0x09);?
?? //調(diào)用此函數(shù),獲取從端點1發(fā)來的8字節(jié)KeyID;??
??? for(tmpInt=0;tmpInt ??????? KeyID_Get[tmpInt]=ReadBuffer[tmpInt+1];? ??? return TRUE;? }? BOOL??CUsbKey::SetKeyID()??? // Set_KeyID子程序? {?? int i;? ??? long result;? ??? int DataBuffer[16];? ??? WriteBuffer[0]=0;?????????? //寫緩沖區(qū)首字節(jié)清0,作為Set_Feature函數(shù)的要求? ??? char *c;????????????????? //獲得對話框內(nèi)輸入8字節(jié)新KeyID字符串的指針? ??? c=(char *)(LPCSTR)str_KeyIDSet;? ??? for (i=0;i ??????? DataBuffer[i]=*c++;? ??? ……?? //此處省略了對輸入的8個字節(jié)的KeyID的16進制檢查代碼? ??? for(i=0;i<8;i++)? ??? ??? WriteBuffer[i+1]=DataBuffer[2*i]+DataBuffer[2*i+1];? ??? result=HidD_SetFeature(HidDevice,WriteBuffer, 0x09);? ??? return? TRUE;? }? ??? (4)程序運行結果,。? ??? 編譯連接之后,最終會生成可執(zhí)行文件KEYDEMO.exe,。執(zhí)行它即可SK通信,實現(xiàn)各種功能。? 參考文獻? 1 王云飛.USB系統(tǒng)研究.研究生論文,北京:清華大學,2001? 2 MOTOROLA. MC68HC908JB8 Technical Data. 2000? 3 Chris Cant (美)著,孫義譯.Windows WDM設備驅動程序開發(fā)指南.北京:機械工業(yè)出版社,2000? 4 Bruce Schneier(美)著,吳世忠譯.應用密碼學——協(xié)議,、算法與C源程序.北京:機械工業(yè)出版社,2000? 5 USB Implementers' Forum.Universal Serial Bus Specification, Revision 1.0. January 15, 1996