Получить прогресс вычисления SHA1 с использованием SHA1CryptoServiceProvider - PullRequest
1 голос
/ 27 июня 2011

В настоящее время я внедряю в свой код C ++ / CLI функцию, которая возвращает значение SHA1 файла.Это приложение Windows Forms в Visual Studio.

Я решил реализовать класс .NetFramework SHA1CryptoServiceProvider, потому что он действительно быстрый (поверьте мне).Я протестировал несколько алгоритмов, но ни один из них не был настолько быстрым, как класс SHA1CryptoServiceProvider.

Проблема в том, что в моем приложении есть индикатор выполнения, показывающий ход вычисления 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 Ответ

3 голосов
/ 28 июня 2011

Наконец-то я это сделал.Я выложу код, может быть, кто-то найдет его полезным.Я знаю, что код не чистый, я все еще учусь.Он может вычислять SHA1 файлов, размер которых превышает 2 ^ 31 байт.Протестировал его на 22ГБ файле.Прекрасно работает в 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);
...