基於SHA-256的HMAC文件校驗器
作者:Gamsn
HMAC即帶密鑰的HASH函數,用它產生的報文鑑別碼(MAC)可以實現報文鑑別。這裏我將其做成一個軟件,用於對文件的合法性進行校驗。以下我先簡單介紹軟件相關背景知識再介紹其代碼實現。
一、背景知識簡介
有時候進行通信的雙方基於安全的考慮需要對對方發過來的消息進行校驗,以確定消息是未經第三方修改過的。這種校驗可以這樣進行:
*其中,生成校驗碼的算法一般採用HMAC,它保證了第三方在不知密鑰的情況下,不可能在修改消息後可以同時修改校驗碼使之與修改後的消息匹配。
*在整個過程中消息是公開的(未經加密的),算法只提供消息的完整性校驗而不提供保密性,保密性可由公鑰加密算法現實,這裏不作討論。
二、軟件的實現
我做的該軟件是可以對電腦磁盤上的任意一文件生成一校驗文件.vri(密鑰由用戶自己輸入),根據該校驗文件可以在需要之時對相應的文件進行校驗。具體做法將在後面的例子中給出。
程序中的HMAC算法的HASH函數我採用的是SHA-256算法,它比起MD5和SHA-1來要安全。(其實因爲不是正式的安全產品,所以在本程序中採用MD5或SHA-1也未嘗不可)。
*HMAC的結構如下圖所示:
圖一 HMAC的結構
圖中各符號定義如下:
IV =作爲HASH函數輸入的初始值 M =HMAC的消息輸入 Yi =M的第i個分組,0<=i<=(L-1) b =每一分組所含的位數 n =嵌入的HASH函數所產生的HASH碼長 K =密鑰 K+ =爲使K爲b位長而在K左邊填充0後所得的結果 ipad =0x36重複b/8次的結果 opad =0x5c重複b/8次的結果
對於特定的HASH函數,b、n都是固定的,所以在程序的HMAC類中,n被定義爲宏Mn,b被定義爲Mb,值分別爲32和64。由於該結構的效率較低,不利於實用化。於是有人提出了一個HMAC的高效實現方案。
*HMAC的有效實現方案如下:
圖二 HMAC的有效實現方案
其中的HASH即爲SHA-256。
圖中左邊所示爲預計算,右邊爲對每條消息的計算。在密鑰不變的情況下只需進行一次預計算,以後在產生校驗碼時就只用到右邊的計算了。這樣就可以提高效率。
需要說明的是,大家在閱讀我寫的HMAC的類可能會發現,在每次計算時都進行了左右兩邊的計算(不論密鑰怎樣)。這是因爲我考慮到個人用戶可能會不時地對密鑰進行更換,並且應用場合也不對效率有特別的要求。當然這樣做並沒有體現出HMAC有效實現方案的優點。
另外還有一點就是我對密鑰的填充是填充的低位,即密鑰右邊,這和上述方案有不同(方案上說是要填充在高位,即左邊),在此說明,以使大家在看源代碼的時候不至於疑惑。
以上有效實現方案在HMac類中現實,HASH函數sha-256在Sha256類中實現。由於這裏主要說的是HMAC,sha-256只是作爲一個黑盒子,所以不多解釋。
程序中的Mac類與HAMC和HASH函數都無關,只是一個存放結果的介質,它甚至都沒有成員函數,我也在考慮是不是可以不把它做成一個類。
爲了便於讀者閱讀HMac類中的各變量基本上採用圖二中的各標識符標識。
對於下面一段代碼讀者可能會有疑惑,明明是該得到第一個預計算的結果,m_dwA1—m_dwH1是什麼呢?
for(i=0;i<Mb;i++) S[i]=sKeyplus[i]^ipad[i]; m_sha256.Init(Mb); m_sha256.GenW(S,Mb); m_sha256.Steps(); m_dwA1=m_sha256.OA; m_dwB1=m_sha256.OB; m_dwC1=m_sha256.OC; m_dwD1=m_sha256.OD; m_dwE1=m_sha256.OE; m_dwF1=m_sha256.OF; m_dwG1=m_sha256.OG; m_dwH1=m_sha256.OH;其實m_dwA1—m_dwH1就是第一個預計算的輸出。這裏因爲這個輸出有256位,於是我把它拆成了8個32位。同理,第二個預計算的輸出爲m_dwA2—m_dwH2。
此外,程序中關於文件拖放和文件保存打開的部分(包括串行化等)對於初學者來說都是一個不錯的借鑑,當然高手就不需在意了。下面將給出一個例子使讀者的認識感性化一點。
三、例子
我有一張非常重要的圖片傳給你,如下:
圖三 例圖 VeriFileimg3
在傳這張圖的同時附上它的校驗文件“important.vri”。(該校驗文件在源代碼壓縮包)
而你收到的圖片如下:(它在傳送中在8,46處被非法的第三方修改了一個象素)
圖四 例圖VeriFileimg4
你用該軟件對其進行校驗可以如下操作:
- 運行該軟件,打開important.vri(打開方式有兩種,你可以從菜單‘文件-打開’中打開,也可以直接把文件拖進程序窗口中。)
(第一次運行該軟件後,程序會創建一個對vri文件的關聯,以後打開vri文件就能以雙擊vri文件打開了。); - 將要校驗的文件拖入程序窗口中,在彈出的對話框中選否;或者是從菜單‘校驗文件-驗證源文件’中打開;
- 然後程序要求輸入校驗密鑰,這裏你和我約定的密鑰爲gamsn,也就是輸入gamsn;
- 程序會計算源文件的校驗碼值,並告訴你結果;
由源文件生成校驗文件的操作也很簡單,從菜單‘校驗文件-生成校驗文件’中選中你的源文件,然後在彈出的對話框中輸入密鑰就可以了。提醒一下,密鑰最大有效長度爲16字節,中英文不限。生成的校驗文件都自動以vri爲後綴名。
四、結束語
大概情況就是如此,大家有什麼問題或指正可以與我聯繫,謝謝!
另外如果諸君對HASH函數感興趣的話可以參考 William Stallings 的 Cryptography and Network Security Principles and Practices 一書第三版。該書不是編程方面的指南,而是密碼與網安方面的專業教材。它的中文版也譯得不錯,是一本好書。