2011-06-27 94 views
1

目前,我正在向我的C++/CLI代碼實現一個返回文件SHA1值的函數。它是Visual Studio中的Windows窗體應用程序。使用SHA1CryptoServiceProvider獲取正在計算的SHA1的進度

我選擇實施.NetFramework類SHA1CryptoServiceProvider,因爲它非常快(相信我)。我測試了幾種算法,但都沒有像SHA1CryptoServiceProvider類那麼快。

問題是,在我的應用程序中有一個progressBar,顯示計算SHA1的進度,而SHA1CryptoServiceProvider類沒有任何返回計算SHA1進度的函數。

下面是代碼:

using namespace System::Security::Cryptography; 
using namespace System::IO; 

StreamReader^ Reader = gcnew StreamReader("C:\\abc.exe"); 
SHA1CryptoServiceProvider^ SHA1 = gcnew SHA1CryptoServiceProvider(); 

String^ Hash = ""; 

Hash = BitConverter::ToString(SHA1->ComputeHash(Reader->BaseStream)); 
return Hash; 
+1

您可以鉤入流中,即將streamreader包裝在您自己的流類中,該流類可以計算讀取和報告的字節數? – Rup

+0

這種報告進度的方法是我想要實現的。類似這樣的: 1.我們打開文件 2.我們讀取緩衝區中的X個字節 3.我們調用ComputeHash(緩衝區) 但是如何對其進行編碼?我的意思是ComputeHash(緩衝區)? – Darxis

回答

3

最後我都做到了。我發佈代碼,也許有人會發現它有用。我知道代碼不乾淨,我仍然在學習。它可以計算大於2^31字節的文件的SHA1。測試它在一個22GB的文件。在backgroundWorker中工作正常:)

#define SHA1_BUFFER_SIZE 65535 
//input buffer 
array<unsigned char,1>^ buf = gcnew array<unsigned char,1>(SHA1_BUFFER_SIZE); 
pin_ptr<unsigned char> pointer = &buf[0]; 

//Open file in 64-bit mode 
FILE *file = _fopeni64("some_large_file.txt","rb"); 
SHA1CryptoServiceProvider^ SHA1 = gcnew SHA1CryptoServiceProvider(); 

//Move pointer to End of File 
_fseeki64(file,0,SEEK_END); 
//Read pointer position (file size) 
unsigned __int64 size = (__int64)_ftelli64(file); 

// Move pointer to begining of file 
_fseeki64(file,0,SEEK_SET); 
__int64 i = 1; // counter 
float wyn = 0; // help variable for progress Percentage (float) 
__int64 conv = 0; // help variable for progress Percentage (int) 

//output buffer 
array<unsigned char,1>^ outputbuffer = gcnew array<unsigned char,1>(SHA1_BUFFER_SIZE); 
while(1) 
{ 
    //Read SHA1_BUFFER_SIZE bytes to buffer 
    size_t bufLen = fread(pointer, 1, SHA1_BUFFER_SIZE, file); 
    if (bufLen == 0) //End of file 
    { 
     if (ferror(file)) //Error opening file 
      return; 
     break; 
    } 
    //buffer has the last block of bytes of the file 
    if (SHA1_BUFFER_SIZE*i >= size ) 
     SHA1->TransformFinalBlock(buf,0,bufLen); 
    else 
     SHA1->TransformBlock(buf,0,bufLen,outputbuffer,0); 

    wyn = SHA1_BUFFER_SIZE*100; /* Getting */ 
    wyn /= size;    /* the  */ 
    wyn *= i;     /* progress */ 
    conv = wyn;     /* Percentage */ 
    ComputeSHA1->ReportProgress(conv); 
    \\Update our progressBar 
    i++; 
} //End main loop 

String^ sHash = ""; 
//Get the computed hash and convert to System::String 
sHash = BitConverter::ToString(SHA1->Hash); 
//Replace the '-' characters in hash to white spaces 
sHash = sHash->Replace('-',' '); 
//Removing whitespaces from hash 
sHash = System::Text::RegularExpressions::Regex::Replace(sHash, "\\s+", System::String::Empty); 

//Filling a textBox with the SHA1 
ComputeSHA1->ReportProgress(0,sHash); 
+2

我很好奇:需要多長時間(在掛鐘時間)來計算這個22GB文件的散列? – TonyK

+0

@TonyK恰好4:30.05(當然是分鐘,而不是幾小時)文件大小22 675 783 680字節,所以哈希速度大約爲80MB/s。有待改善... – Darxis