【項目】磁盤文件管理工具

項目介紹

該項目創建的目的爲刪除磁盤中重複文件,通過計算指定路徑下的文件指紋(數字簽名)來判斷兩個文件是否相同,從而按照文件名、文件指紋或模糊匹配刪除相同文件

項目原理

計算機簽名方法

數字簽名,就是隻有信息的發送者才能產生的別人無法僞造的一段數字串,這段數字串同時也是對信息的發送者發送信息真實性的一個有效證明。 是一種類似寫在紙上的普通的物理簽名

常用的數字簽名方法主要有:
HASH算法 ,此算法主要包括MD(信息摘要)和SHA(安全散列算法)兩類 。DSA、ECDSA、橢圓曲線數字簽名算法,微軟產品的序列號驗證算法使用的就是ECDSA。與傳統的數字簽名算法相比,速度快,強度高,簽名短

計算機簽名 MD5

MD5簡介

MD5是由Ron Rivest在1991設計的一種信息摘要(message-digest )算法,當給定任意長度的信息,MD5 會產生一個固定的 128 位“指紋”或者叫信息摘要。從理論的角度,所有的信息產生的 MD5 值都不同,也無法通過給定的 MD5 值產生任何信息,即不可逆

  1. 功能
    輸入任意長度的信息,經過處理,輸出爲 128 位的信息(數字指紋)
    不同的輸入得到的不同的結果(唯一性),要使兩個不同的信息產生相同的摘要,操作數量級在 2^64 次方
    根據128位的輸出結果不可能反推出輸入的信息,根據給定的摘要反推原始信息,它的操作數量級在 2^128 次

  2. 用途

防止信息被篡改

1)當發送電子文檔的同時發送文檔的 MD5 值,接收後計算 MD5 值,若結果相同則沒有被篡改
2)作爲文件下載安全驗證,在下載網絡文件或程序時,爲了防止不法分子在安裝程序中添加木馬,在網站上公佈由安裝文件得到的MD5輸出結果。用戶下載完成,在本地計算MD5值,比較結果,驗證文件是否完整和安全

防止直接看到密碼明文

現在很多網站在數據庫存儲用戶的密碼的時候都是存儲用戶密碼的MD5值。就算不法分子得到數據庫種用戶密碼的MD5值,也無法知道用戶的密碼。比如在UNIX系統中用戶的密碼就是以MD5(或其它類似的算法)經加密後存儲在文件系統中。當用戶登錄的時候,系統把用戶輸入的密碼計算成MD5值,然後再去和保存在文件系統中的MD5值進行比較,進而確定輸入的密碼是否正確。通過這樣的步驟,系統在並不知道用戶密碼的明碼的情況下就可以確定用戶登錄系統的合法性。這不但可以避免用戶的密碼被具有系統管理員權限的用戶知道,而且還在一定程度上增加了密碼被破解的難度

防止抵賴(數字簽名)

這需要一個第三方認證機構。例如A寫了一個文件,認證機構對此文件用MD5算法產生摘要信息並做好記錄。若以後A說這文件不是他寫的,權威機構只需對此文件重新產生摘要信息,然後跟記錄在冊的摘要信息進行比對,相同的話,就證明是A寫的了。這就是所謂的“數字簽名”

MD5 算法步驟

MD5的算法輸入爲以bit爲單位的信息(1 byte = 8 * bit),經過處理,得到一個128bit的摘要信息。這128位的摘要信息在計算過程中分成4個32bit的子信息,存儲在4個buffer(A,B,C,D)中,它們初始化爲固定常量。MD5算法然後使用每一個512bit的數據塊去改變A,B,C,D中值,所有的數據處理完之後,把最終的A,B,C,D值拼接在一起,組成128bit的輸出。處理每一塊數據有四個類似的過程,每一個過程由16個相似的操作流組成,操作流中包括非線性函數,相加以及循環左移。MD5算法大致可分爲5個步驟:

  1. 添加填充位
    信息的最尾部(不是每一塊的尾部)要進行填充,使其最終的長度length(以bit爲單位)滿足length % 512 = 448,這一步始終要執行,即使信息的原始長度恰好符合上述要求
    填充規則:第一個bit填充位填 ‘1’ ,後續bit填充位都填 ‘0’ ,最終使消息的總體長度滿足上述要求。總之,至少要填充 1 bit,至多填充 512 bit

  2. 添加bit長度
    添加一個64bit大小的length,length表示原始消息(未填充之前)的bit長度,極端情況,如果消息長度超過264,那麼只使用前264bit消息,這一步完成之後,消息的最終長度變爲(length + 64) % 512 = 0,即length爲512的整數倍。從這裏再去看第一步,至少需要填充 8 bit,有以下幾種情況:
    1)消息原始長度 % 512 = 448,這時候原始長度符合要求,但是根據填充規則,仍然要至少填1bit的 ‘1’,後面還剩63bit,不夠添加長度,所以需要再加一塊數據(512bit),這樣後面63bit填0,新加的數據前448bit填0,最後64bit填數據原始長度,長度值是放在最後一塊數據的最後64bit
    2)消息原始長度 % 512 < 448,此時最後一塊數據長度不大於440bit,最後64bit填數據長度,需要填充的bit數不小於8
    3)消息原始長度 % 512 > 448,此時最後一塊數據長度不小於456,最多504,剩餘bit不夠添加64位長度,和假設1相同,需要增加一塊數據,最後64位添加長度,其餘填充0

  3. 初始化MD buffer(A,B,C,D)
    用4-word buffer(A, B, C, D)計算摘要,這裏A,B,C,D各爲一個32bit的變量,這些變量初始化爲下面的十六進制值,低字節在前

/*word A: 01 23 45 67
 word B: 89 ab cd ef
 word C: fe dc ba 98
 word D: 76 54 32 10
*/
 // 初始化A,B,C,D 
 _atemp = 0x67452301; 
 _btemp = 0xefcdab89; 
 _ctemp = 0x98badcfe; 
 _dtemp = 0x10325476;
  1. 按512位數據逐塊處理輸入信息
    512bit數據爲一個處理單位,暫且稱爲一個數據塊chunk,每個chunk經過4個函數(F, G, H, I)處理,這四個函數輸入爲3個32位(4字節)的值,產生一個32位的輸出。四個函數如下所示:
/*
F(x,y,z) = (x & y) | ((~x) & z) 
G(x,y,z) = (x & z) | ( y & (~z)) 
H(x,y,z) = x ^ y ^ z 
I(x,y,z) = y ^ (x | (~z))
 */

處理過程中要用一個含有64個元素的表K[1…64],表中的元素值由sin函數構建,K[i]等於2^(32) * abs(sin(i))的整數部分,即:

/*
K[i] = floor(2^(32) * abs(sin(i + 1))) // 因爲此處i從0開始,所以需要sin(i + 1) 
*/
for (int i = 0; i < 64; i++) 
{ 
    _k[i] = (size_t)(abs(sin(i + 1)) * pow(2, 32)); 
}

在處理一個chunk(512bit)的數據時,會把這個chunk再細分成16組4字節數據,一個chunk經過4輪進行處理,每輪都會把chunk的所有數據處理一遍,每輪有16個相似的子操作,所以一個chunk的數據要進行64個子操作計算之前先保存MD buffer的當前值:
a = A, b = B, c = C, d = D

第一輪:F函數處理(0 <= i <= 15)
在這裏插入圖片描述
在這裏插入圖片描述

F = F(b, c, d) 
d = c
c =b
b = b + shift((a + F + k[i] + chunk[g]), s[i]) 
a = d

第二輪:G函數處理 (16 <= i <= 31)
在這裏插入圖片描述
在這裏插入圖片描述

G = G(b, c, d) 
d = c 
c =b 
b = b + shift((a + G + k[i] + chunk[g]), s[i]) 
a = d

第三輪:H函數處理(32 <= i <= 47)
在這裏插入圖片描述
在這裏插入圖片描述

H = H(b, c, d) 
d = c 
c =b 
b = b + shift((a + H + k[i] + chunk[g]), s[i]) 
a = d

第四輪:I函數處理(48 <= i <= 63)
在這裏插入圖片描述
在這裏插入圖片描述

I = I(b, c, d) 
d = c 
c =b 
b = b + shift((a + I + k[i] + chunk[g]), s[i]) 
a = d

注:<<<s表示循環左移操作

/*
s[ 0..15] = { 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22 } 
s[16..31] = { 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20 }
s[32..47] = { 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23 } 
s[48..63] = { 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21 }
 */
size_t s[] = { 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 
            12, 17, 22, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 
            4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 6, 10, 
            15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21 };
  if (0 <= i < 16) g = i; 
  if (16 <= i < 32) g = (5 * i + 1) % 16; 
  if (32 <= i < 48) g = (3 * i + 5) % 16;
  if(48 <= i < 63) g = (7 * i) % 16;

一個chunk數據處理完之後,更新MD buffer的值A, B, C, D

A = a + A; 
B = b + B; 
C = c + C; 
D = d + D;
  1. 摘要輸出

拼接4個buffer(A,B,C,D)中的摘要信息,以A中的低位字節開始,D的高位字節結束。最終的輸出是128bit摘要信息的16進製表示,故最後輸出一個32長度的摘要信息

項目流程及模塊介紹

  1. 寫出計算 MD5 值的程序(MD5.c & MD5.h)
  2. 寫出根據 MD5 值、文件名、模糊匹配刪除相同文件等關於文件處理的程序(fileManager.cpp & fileManager.h)
  3. 將上述關於文件操作的程序包到一個工具類中(fileManagerTool.cpp & fileManagerTool.h)
  4. 寫出進行指定目錄下文件檢索找到文件的程序(fileutil.cpp & fileutil.h)
  5. 最後完成菜單設計,將功能實現(test.cpp)
  6. 對基本功能進行測試

    代碼鏈接.
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章