📄 messagedigests.pas
字号:
procedure TMessageDigest.RequireCompletion;begin if not Completed then raise Exception.Create('Message digest not complete.');end;procedure TMessageDigest.RequireIncompletion;begin if Completed then raise Exception.Create('Message digest already complete.');end;{----------------------------------TMD2----------------------------------------}constructor TMD2.Create;{ Pre: None. Post: Returns an instance of class TMD2, capable of computing message digests using the MD2 algorithm.}begin inherited CreateInternal(MD2BlockSize, MD2DigestSize);end;destructor TMD2.Destroy;begin inherited;end;procedure TMD2.Clear;begin inherited; FillChar(Checksum, SizeOf(Checksum), 0); FillChar(Buffer, SizeOf(Buffer), 0);end;const MD2Permutation: array [Byte] of Byte = ( 41, 46, 67, 201, 162, 216, 124, 1, 61, 54, 84, 161, 236, 240, 6, 19, 98, 167, 5, 243, 192, 199, 115, 140, 152, 147, 43, 217, 188, 76, 130, 202, 30, 155, 87, 60, 253, 212, 224, 22, 103, 66, 111, 24, 138, 23, 229, 18, 190, 78, 196, 214, 218, 158, 222, 73, 160, 251, 245, 142, 187, 47, 238, 122, 169, 104, 121, 145, 21, 178, 7, 63, 148, 194, 16, 137, 11, 34, 95, 33, 128, 127, 93, 154, 90, 144, 50, 39, 53, 62, 204, 231, 191, 247, 151, 3, 255, 25, 48, 179, 72, 165, 181, 209, 215, 94, 146, 42, 172, 86, 170, 198, 79, 184, 56, 210, 150, 164, 125, 182, 118, 252, 107, 226, 156, 116, 4, 241, 69, 157, 112, 89, 100, 113, 135, 32, 134, 91, 207, 101, 230, 45, 168, 2, 27, 96, 37, 173, 174, 176, 185, 246, 28, 70, 97, 105, 52, 64, 126, 15, 85, 71, 163, 35, 221, 81, 175, 58, 195, 92, 249, 206, 186, 197, 234, 38, 44, 83, 13, 110, 133, 40, 132, 9, 211, 223, 205, 244, 65, 129, 77, 82, 106, 220, 55, 200, 108, 193, 171, 250, 36, 225, 123, 8, 12, 189, 177, 74, 120, 136, 149, 139, 227, 99, 232, 109, 233, 203, 213, 254, 59, 0, 29, 57, 242, 239, 183, 14, 102, 88, 208, 228, 166, 119, 114, 248, 235, 117, 75, 10, 49, 68, 80, 180, 143, 237, 31, 26, 219, 153, 141, 51, 159, 17, 131, 20 );procedure TMD2.TransformBlocks(const Blocks; const BlockCount: Longint);{ Pre: Addr(Blocks) <> nil and Blocks is an exact integral number of blocks of size MD2BlockSize and BlockCount represents the number of blocks in Blocks. Post: Self will update its state to reflect the message digest after processing Blocks with the MD2 algorithm. This includes updating the checksum so that when Complete is called, the digest can be correctly computed.}const NumRounds = 18;var I: Longint; J, T, K: Byte; PBlock: PMD2Block; PC, PJ, PX, PX16, PX32: ^Byte;begin PBlock := Addr(Blocks); (*$IFNDEF PreDelphi3*) Assert(Assigned(PBlock), 'TMD2.TransformBlocks: Addr(Blocks) = nil.'); { Assert(BlockCount mod MD2BlockSize = 0, 'TMD2.TransformBlocks: BlockCount mod MD2BlockSize <> 0.'); } (*$ENDIF*) for I := 1 to BlockCount do begin { Checksum Ith block. } PJ := Pointer(PBlock); PC := Addr(Checksum); for J := Low(Checksum) to High(CheckSum) do begin ChecksumL := PC^ xor MD2Permutation[PJ^ xor ChecksumL]; PC^ := ChecksumL; Inc(PJ); Inc(PC); end; { Copy Ith block into X. } PJ := Pointer(PBlock); PX := Addr(Buffer); PX16 := PX; Inc(PX16, 16); PX32 := PX; Inc(PX32, 32); for J := 0 to 15 do begin PX16^ := PJ^; PX32^ := PX16^ xor PX^; Inc(PJ); Inc(PX); Inc(PX16); Inc(PX32); end; { Do 18 rounds. } T := 0; for J := 0 to Pred(NumRounds) do begin PX := Addr(Buffer); for K := Low(Buffer) to High(Buffer) do begin T := PX^ xor MD2Permutation[T]; PX^ := T; Inc(PX); end; Inc(T, J); end; { Advance pointer to next block. } Inc(PBlock); end; Move(Buffer, PDigest^, FDigestSize); inherited;end;procedure TMD2.Complete;{ Pre: None. Post: This will complete the digestion of the data. Any remaining bytes (i.e. left over from an impartial block) will be padded in accordance with the MD2 standard and transformed. Finally, the checksum will be transformed. The property HashValue will represent the 16-byte digest of the data that have been input since creation of this instance.}var NumBytesNeeded: Integer; P: ^Byte;begin RequireIncompletion; NumBytesNeeded := FBlockSize - NumLastBlockBytes; P := PLastBlock; Inc(P, NumLastBlockBytes); FillChar(P^, NumBytesNeeded, NumBytesNeeded); TransformBlocks(PLastBlock^, 1); Move(Checksum, PLastBlock^, SizeOf(Checksum)); TransformBlocks(PLastBlock^, 1); inherited;end;class function TMD2.AsString: string;begin Result := 'MD2';end;{--------------------------------TMD4Family------------------------------------}constructor TMD4Family.CreateInternal(const BlockSize, DigestSize: Integer; const InitialChainingValues; const IsBigEndian: Boolean);{ Pre: InitialChainingValues <> nil and number of bytes in InitialChainingValues = FDigestSize. Post: Self.FInitialChainingValues = InitialChainingValues by value, but not by address. Returns an instance of class TMD4Family, capable of computing message digests using one of algorithms in the MD4 family.}begin (*$IFNDEF PreDelphi3*) Assert(Assigned(Addr(InitialChainingValues)), 'TMD4Family.InitializeChainingValues: InitialChainingValues = nil.'); (*$ENDIF*) GetMem(PInitialChainingValues, DigestSize); Move(InitialChainingValues, PInitialChainingValues^, DigestSize); inherited CreateInternal(BlockSize, DigestSize); FIsBigEndian := IsBigEndian;end;destructor TMD4Family.Destroy;begin FreeMem(PChainingVars); FreeMem(PInitialChainingValues); inherited;end;procedure TMD4Family.Clear;begin inherited; if not Assigned(PChainingVars) then GetMem(PChainingVars, DigestSize); Move(PInitialChainingValues^, PChainingVars^, DigestSize);end;procedure TMD4Family.Complete;{ Pre: None. Post: This will complete the digestion of the data. Any remaining bytes (i.e. left over from an impartial block) will be padded in accordance with the MD4 family standard and transformed. The property HashValue will represent the message digest of the data that have been input.}var NumBytesNeeded: Integer; MessageLength: Int64; P: ^Byte; T: DWORD; PD: ^TChainingVar; I: Integer;begin RequireIncompletion; MessageLength := BitsPerByte * (FBlockSize * FBlocksDigested + NumLastBlockBytes); P := PLastBlock; Inc(P, NumLastBlockBytes); P^ := $80; { Set the high bit. } Inc(P); Inc(NumLastBlockBytes); { # bytes needed = Block size - # bytes we already have - 8 bytes for the message length. } NumBytesNeeded := FBlockSize - NumLastBlockBytes - SizeOf(MessageLength); if NumBytesNeeded < 0 then begin { Not enough space to put the message length in this block. } FillChar(P^, FBlockSize - NumLastBlockBytes, 0); TransformBlocks(PLastBlock^, 1); { Put it in the next one. } NumBytesNeeded := FBlockSize - SizeOf(MessageLength); P := PLastBlock; end; FillChar(P^, NumBytesNeeded, 0); Inc(P, NumBytesNeeded); if FIsBigEndian then with TDoubleDWORD(MessageLength) do begin { Swap the bytes in MessageLength. } with TFourByte(L) do begin T := B1; B1 := B4; B4 := T; T := B2; B2 := B3; B3 := T; end; with TFourByte(H) do begin T := B1; B1 := B4; B4 := T; T := B2; B2 := B3; B3 := T; end; { Swap the DWORDs in MessageLength. } T := L; L := H; H := T; end; Move(MessageLength, P^, SizeOf(MessageLength)); TransformBlocks(PLastBlock^, 1); Move(PChainingVars^, PDigest^, FDigestSize); if FIsBigEndian then begin { Swap 'em again. } PD := PDigest; for I := 1 to FDigestSize div SizeOf(PD^) do begin with TFourByte(PD^) do begin T := B1; B1 := B4; B4 := T; T := B2; B2 := B3; B3 := T; end; Inc(PD); end; end; inherited;end;{-----------------------------------TMD4---------------------------------------}const MD4Z: array [0..47] of Byte = ( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15, 0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15 ); MD4S: array [0..47] of Byte = ( 3, 7, 11, 19, 3, 7, 11, 19, 3, 7, 11, 19, 3, 7, 11, 19, 3, 5, 9, 13, 3, 5, 9, 13, 3, 5, 9, 13, 3, 5, 9, 13, 3, 9, 11, 15, 3, 9, 11, 15, 3, 9, 11, 15, 3, 9, 11, 15 ); MD4InitialChainingValues: TMD4ChainingVarArray = ( $67452301, $efcdab89, $98badcfe, $10325476 );constructor TMD4.Create;{ Pre: None. Post: Returns an instance of class TMD4, capable of computing message digests using the MD4 algorithm.}begin inherited CreateInternal(MD4BlockSize, MD4DigestSize, MD4InitialChainingValues, False);end;destructor TMD4.Destroy;begin inherited;end;procedure TMD4.TransformBlocks(const Blocks; const BlockCount: Longint);{ Pre: Addr(Blocks) <> nil and Blocks is an exact integral number of blocks of size MD4BlockSize and BlockCount represents the number of blocks in Blocks. Post: Self will update its state to reflect the message digest after processing Blocks with the MD4 algorithm.}var I, J: Integer; T: TChainingVar; P: PMD4Block; A, B, C, D: TChainingVar;begin P := Addr(Blocks); (*$IFNDEF PreDelphi3*) Assert(Assigned(P), 'TMD4.TransformBlocks: Addr(Blocks) = nil.'); { Assert(BlockCount mod MD4BlockSize = 0, 'TMD4.TransformBlocks: BlockCount mod MD4BlockSize <> 0.'); } (*$ENDIF*) for I := 1 to BlockCount do begin { Initialize working variables. } A := PMD4ChainingVarArray(PChainingVars)^[mdA]; B := PMD4ChainingVarArray(PChainingVars)^[mdB]; C := PMD4ChainingVarArray(PChainingVars)^[mdC]; D := PMD4ChainingVarArray(PChainingVars)^[mdD]; { Round 1. } for J := 0 to 15 do begin T := A + ((B and C) or (not B and D)) + P^(.MD4Z[J].); A := D; D := C; C := B; B := CircularSHL(T, MD4S[J]); end; { Round 2. } for J := 16 to 31 do begin T := A + ((B and C) or (B and D) or (C and D)) + P^(.MD4Z[J].) + $5a827999; A := D; D := C; C := B; B := CircularSHL(T, MD4S[J]); end; { Round 3. } for J := 32 to 47 do begin T := A + (B xor C xor D) + P^(.MD4Z[J].) + $6ed9eba1; A := D; D := C; C := B; B := CircularSHL(T, MD4S[J]); end; Inc(P); { Update chaining values. } Inc(PMD4ChainingVarArray(PChainingVars)^[mdA], A); Inc(PMD4ChainingVarArray(PChainingVars)^[mdB], B); Inc(PMD4ChainingVarArray(PChainingVars)^[mdC], C); Inc(PMD4ChainingVarArray(PChainingVars)^[mdD], D); end; inherited;end;class function TMD4.AsString: string;begin Result := 'MD4';end;{----------------------------------TMD5----------------------------------------}const MD5Y: array [0..63] of DWORD = ( { Round 1. } $d76aa478, $e8c7b756, $242070db, $c1bdceee, $f57c0faf, $4787c62a, $a8304613, $fd469501, $698098d8, $8b44f7af, $ffff5bb1, $895cd7be, $6b901122, $fd987193, $a679438e, $49b40821, { Round 2. } $f61e2562, $c040b340, $265e5a51, $e9b6c7aa, $d62f105d, $02441453, $d8a1e681, $e7d3fbc8, $21e1cde6, $c33707d6, $f4d50d87, $455a14ed, $a9e3e905, $fcefa3f8, $676f02d9, $8d2a4c8a, { Round 3. } $fffa3942, $8771f681, $6d9d6122, $fde5380c, $a4beea44, $4bdecfa9, $f6bb4b60, $bebfbc70, $289b7ec6, $eaa127fa, $d4ef3085, $04881d05, $d9d4d039, $e6db99e5, $1fa27cf8, $c4ac5665, { Round 4. } $f4292244, $432aff97, $ab9423a7, $fc93a039, $655b59c3, $8f0ccc92, $ffeff47d, $85845dd1, $6fa87e4f, $fe2ce6e0, $a3014314, $4e0811a1, $f7537e82, $bd3af235, $2ad7d2bb, $eb86d391 ); MD5Z: array [0..63] of Byte = ( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 1, 6, 11, 0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12, 5, 8, 11, 14, 1, 4, 7, 10, 13, 0, 3, 6, 9, 12, 15, 2, 0, 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9 ); MD5S: array [0..63] of Byte = ( 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 ); MD5InitialChainingValues: TMD5ChainingVarArray = ( $01234567, $89abcdef, $fedcba98, $76543210 );constructor TMD5.Create;{ Pre: None. Post: Returns an instance of class TMD5, capable of computing message digests using the MD5 algorithm.}begin inherited CreateInternal(MD5BlockSize, MD5DigestSize, MD4InitialChainingValues, False);end;destructor TMD5.Destroy;begin inherited;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -