- Сообщения
- 8,071
- Решения
- 20
- Реакции
- 6,877
Достаточно часто, при работе с различными онлайн-сервисами нам приходится сталкиваться с хэшированием. Наиболее часто используемые при этом алгоритмы — MD5 и SHA1 (ну, по крайней мере, мне с этими алгоритмами приходится сталкиваться часто, с остальными — намного реже). Буквально недавно столкнулся в очередной раз с вычислением SHA1. Причем хэш необходимо рассчитывать для содержимого файла и передавать этот хэш в заголовках POST-запроса вместе с самим файлом на сервер. Ну, а так как, теоретически, на сервер можно отправлять файлы до 2 Гб, то возник вполне резонный вопрос: какой самый быстрый способ получить хэш SHA1 для файла есть в Delphi 10? Одно дело, когда необходимо получить хэш для строки в несколько сотен символов, а другое — для файла в несколько гигабайт.
Сразу, навскидку, вспомнились:
Покопавшись в исходниках к Delphi 10 нашел модуль:
Как получить SHA1 в Indy:
Как получить SHA1 в Synapse:
Как получить SHA1 в DCPCRYPT (DCP):
Как получить SHA1 в TurboPower LockBox:
Как получить SHA1 в System.Hash:
Для теста я взял несколько файлов следующих размеров: 116 Кб, 1,1 Мб, 791 Мб и 2,1 Гб. Результаты теста, секунды:
[table=head]Пакет|116 Кб|1,1 Мб|791 Мб|2,1 Гб
DCP |0,0015 |0,0206 |9,455 |28,0592
Synapse |0,0041 |0,0373 |32,3996| Error
Indy |0,0035 |0,0329 |23,7571 |164,1033
LockBox |0,0039 |0,0335 |24,3384 |118,3559
System.Hash |0,0014 |0,0103 |7,0152 |20,3686
[/table]
Вот так, товарищи, самым быстрым оказался родной модуль Delphi. А Synapse — единственной библиотекой, которой для получения хэша в обязательном порядке требуется отдавать строку. Отсюда и вылет в Out of Memory на большом файле. Неплохие результаты также показала библиотека DCPCrypt, но какой смысл тащить в проект стороннюю библиотеку, если надо получать только SHA1 и родной модуль Delphi справляется с этим на ура?
Само собой, что я рассмотрел далеко не все имеющиеся возможности и способы того как рассчитать SHA1 в Delphi, а лишь привел результаты экспериментов с теми библиотеками, которыми сам пользовался долгое время или нашел в Сети самыми первыми. Может быть кто-то знает ещё более быстрый способ расчёта SHA1 для больших файлов? Буду очень признателен за представленный пример, который на файле выше 2 Гб покажет время менее 20 сеукунд.
Автор: Vlad. Источник.
Сразу, навскидку, вспомнились:
- Indy и её класс TIdHashSHA1
- Synapse и её функция SHA1
Покопавшись в исходниках к Delphi 10 нашел модуль:
- System.Hash
Как получить SHA1 в Indy:
Код:
uses IdHashSHA;
...
var Hash: string;
IdHashSHA1: TIdHashSHA1;
FS: TFileStream;
begin
FS:=TFile.OpenRead('PATH_TO_FILE');
IdHashSHA1:=TIdHashSHA1.Create;
try
S2:=IdHashSHA1.HashStreamAsHex(FS);
finally
IdHashSHA1.Free;
end;
end;
Код:
uses synautil, synacode;
....
Hash:=StrToHex(SHA1(ReadStrFromStream(FS, FS.Size)));
....
Код:
var DCP_sha11: TDCP_sha1;
HashDigest: array of byte;
Hash: string;
begin
DCP_sha11:=TDCP_sha1.Create(nil);
try
DCP_sha11.Init;
DCP_sha11.UpdateStream(FS,FS.Size);
SetLength(HashDigest,DCP_sha11.HashSize div 8);
DCP_sha11.Final(HashDigest[0]);
for i:= 0 to High(HashDigest) do
Hash:= Hash + IntToHex(HashDigest[i],2);
finally
DCP_sha11.Free
end;
end;
Код:
var
SHA1Hash: THash;
CryptoLib: TCryptographicLibrary;
Hash: string;
aByte: byte;
begin
SHA1Hash:=THash.Create(nil);
try
CryptoLib:=TCryptographicLibrary.Create(nil);
try
SHA1Hash.CryptoLibrary:=CryptoLib;
SHA1Hash.Hash:='SHA-1';
SHA1Hash.HashStream(FS);
while SHA1Hash.HashOutputValue.Read(aByte, 1) = 1 do
Hash:= Hash+Format('%.2x', [aByte]);
finally
CryptographicLibrary1.Free;
end;
finally
SHA1Hash.Free
end;
end;
Код:
var HashSHA1:THashSHA1;
Hash: string;
read: integer;
buffer: array[0..16383] of byte;
begin
HashSHA1:=THashSHA1.Create;
repeat
read := FS.Read(buffer,Sizeof(buffer));
HashSHA1.Update(buffer,read);
until read <> Sizeof(buffer);
Hash:=HashSHA1.HashAsString;
end;
[table=head]Пакет|116 Кб|1,1 Мб|791 Мб|2,1 Гб
DCP |0,0015 |0,0206 |9,455 |28,0592
Synapse |0,0041 |0,0373 |32,3996| Error
Indy |0,0035 |0,0329 |23,7571 |164,1033
LockBox |0,0039 |0,0335 |24,3384 |118,3559
System.Hash |0,0014 |0,0103 |7,0152 |20,3686
[/table]
Вот так, товарищи, самым быстрым оказался родной модуль Delphi. А Synapse — единственной библиотекой, которой для получения хэша в обязательном порядке требуется отдавать строку. Отсюда и вылет в Out of Memory на большом файле. Неплохие результаты также показала библиотека DCPCrypt, но какой смысл тащить в проект стороннюю библиотеку, если надо получать только SHA1 и родной модуль Delphi справляется с этим на ура?
Само собой, что я рассмотрел далеко не все имеющиеся возможности и способы того как рассчитать SHA1 в Delphi, а лишь привел результаты экспериментов с теми библиотеками, которыми сам пользовался долгое время или нашел в Сети самыми первыми. Может быть кто-то знает ещё более быстрый способ расчёта SHA1 для больших файлов? Буду очень признателен за представленный пример, который на файле выше 2 Гб покажет время менее 20 сеукунд.
Автор: Vlad. Источник.
Последнее редактирование модератором: