1. 程式人生 > >基於SHA-256的HMAC檔案校驗器

基於SHA-256的HMAC檔案校驗器



                   
  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。