Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.139.72.200] |
|
Сообщ.
#1
,
|
|
|
Подскажете как реализовать хэширование MD5 для файла размером > 6GB с использованием именно fundamentals5:
https://github.com/fundamentalslib/fundamen...ils/flcHash.pas ... procedure MD5InitDigest(var Digest: T128BitDigest); procedure MD5Buf(var Digest: T128BitDigest; const Buf; const BufSize: Integer); procedure MD5FinalBuf(var Digest: T128BitDigest; const Buf; const BufSize: Integer; const TotalSize: Int64); Знаю есть другие библиотеки где уже все есть, но нужно именно на fundamentals5. Пробовал делать сам но на данных > 6GB получаю не верный хэш. |
Сообщ.
#2
,
|
|
|
вопрос решён
|
Сообщ.
#3
,
|
|
|
Напиши как решил ?
|
Сообщ.
#4
,
|
|
|
Так несколько раз вызывать MD5Buf с новыми кусками и все
|
Сообщ.
#5
,
|
|
|
ZBugZ
у меня косяк был в том что я для чанков использовал Cardinal, надо было int64. Вот соло MD5 через Stream procedure fuMD5HashFromStream(Stream: TStream; out Result: TBytes); var buffer : array[0..16383] of byte; Size : int64; ReadBytes : int64; TotalBytes : int64; Digest : T128BitDigest; skiptofinal : Boolean; BufSZ, LeftSZ : int64; begin flcHash.MD5InitDigest(Digest); Stream.Seek(0, soFromBeginning); Size := Stream.Size; TotalBytes := 0; if Size > SizeOf(Buffer) then BufSZ := SizeOf(Buffer) else if Size < 64 then ReadBytes := Stream.Read(Buffer, Size) else BufSZ := (Size div 64) * 64; skiptofinal := Size < 64; if not skiptofinal then try repeat LeftSZ := Size - TotalBytes; if LeftSZ < BufSZ then begin if LeftSZ < 64 then begin ReadBytes := Stream.Read(Buffer, BufSZ); skiptofinal := True; Break; end; BufSZ := (LeftSZ div 64) * 64; end; ReadBytes := Stream.Read(Buffer, BufSZ); Inc(TotalBytes, ReadBytes); MD5Buf(Digest, Pointer(@Buffer)^, ReadBytes); until (ReadBytes = 0) or (TotalBytes = Size); finally Stream.Seek(0, soFromBeginning); end; if not skiptofinal then ReadBytes := 0; MD5FinalBuf(Digest, Pointer(@Buffer)^, ReadBytes, Size); SetLength(Result, Length(Digest.Bytes)); Move(PByte(@Digest.Bytes[0])^, PByte(@Result[0])^, Length(Digest.Bytes)); end; А вобще есть встроенные классы, так что можно все хэши этой либы в одну функцию засунуть: Свой тип TFundamentalsHashType для того что бы были CRC32 и JAMCRC32. До Knuth руки не дошли. uses SynCommons .... type TFundamentalsHashType = (fh_Checksum, fh_XOR8, fh_XOR16, fh_XOR32, fh_CRC16, fh_CRC32, fh_JAMCRC32, fh_Adler32, fh_ELF, fh_Knuth, fh_MD5, fh_SHA1, fh_SHA256, fh_SHA512, fh_RipeMD160); .... function RB(A: longint): longint; {-rotate byte of longint} begin RB := (A shr 24) or ((A shr 8) and $FF00) or ((A shl 8) and $FF0000) or (A shl 24); end; procedure fuCommonHashFromFile(HashType: TFundamentalsHashType; FileName: String; out Result: TBytes); var HashClass: AHash; D8 : Byte; D16: Word; D32 : LongWord ; Digest128 : T128BitDigest; Digest160 : T160BitDigest; Digest224 : T224BitDigest; Digest256 : T256BitDigest; Digest384 : T384BitDigest; Digest512 : T512BitDigest; HT : Integer; begin HT := Integer(HashType); if HT > 5 then Dec(HT); if HT > 7 then Dec(HT); HashClass := GetHashClassByType( THashType(HT) ).Create; case HashType of fh_Checksum : HashClass.Init(@D32, '' ); fh_XOR8 : HashClass.Init(@D8, ''); fh_XOR16 : HashClass.Init(@D16, ''); fh_XOR32 : HashClass.Init(@D32, ''); fh_CRC16 : HashClass.Init(@D16, ''); fh_CRC32 : HashClass.Init(@D32, '' ); fh_JAMCRC32 : HashClass.Init(@D32, '' ); fh_Adler32 : HashClass.Init(@D32, ''); fh_ELF : HashClass.Init(@D32, ''); fh_Knuth : ; fh_MD5 : HashClass.Init(@Digest128, ''); fh_SHA1 : HashClass.Init(@Digest160, ''); fh_SHA256 : HashClass.Init(@Digest256, ''); fh_SHA512 : HashClass.Init(@Digest512, ''); fh_RipeMD160 : HashClass.Init(@Digest160, ''); end; HashClass.HashFile(FileName); HashClass.Free; case HashType of fh_Checksum : begin D32 := RB(D32); RawByteStringToBytes( DigestToBufA( D32, 4), Result); end; fh_XOR8 : RawByteStringToBytes( DigestToBufA( D8, 1), Result); fh_XOR16 : begin D16 := swap(D16); RawByteStringToBytes( DigestToBufA( D16, 2), Result); end; fh_XOR32 : begin D32 := RB(D32); RawByteStringToBytes( DigestToBufA( D32, 4), Result); end; fh_CRC16 : begin D16 := swap(D16); RawByteStringToBytes( DigestToBufA( D16, 2), Result); end; //CCITTFALSE fh_CRC32 : begin D32 := RB(not D32); RawByteStringToBytes( DigestToBufA( D32, 4), Result); end; //Без Not будет JAMCRC с not Класический CRC32 fh_JAMCRC32 : begin D32 := RB(D32); RawByteStringToBytes( DigestToBufA( D32, 4), Result); end; fh_Adler32 : begin D32 := RB(D32); RawByteStringToBytes( DigestToBufA( D32, 4), Result); end; //Result := TConverters.ConvertHexStringToBytes( CardinalToHex(D32) ) ; fh_ELF : begin D32 := RB(D32); RawByteStringToBytes( DigestToBufA( D32, 4), Result); end; fh_Knuth : ; fh_MD5 : begin SetLength(Result, Length(Digest128.Bytes)); Move(PByte(@Digest128.Bytes[0])^, PByte(@Result[0])^, Length(Digest128.Bytes)); end; fh_SHA1, fh_RipeMD160 : begin SetLength(Result, Length(Digest160.Bytes)); Move(PByte(@Digest160.Bytes[0])^, PByte(@Result[0])^, Length(Digest160.Bytes)); end; fh_SHA256 : begin SetLength(Result, Length(Digest256.Bytes)); Move(PByte(@Digest256.Bytes[0])^, PByte(@Result[0])^, Length(Digest256.Bytes)); end; fh_SHA512 : begin SetLength(Result, Length(Digest512.Bytes)); Move(PByte(@Digest512.Bytes[0])^, PByte(@Result[0])^, Length(Digest512.Bytes)); end; end; end; |