CryptoMD5.Mod 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. MODULE CryptoMD5; (** AUTHOR "G.F."; PURPOSE "MD5"; *)
  2. IMPORT
  3. S := SYSTEM, Hashes := CryptoHashes, U := CryptoUtils;
  4. TYPE
  5. Buffer = ARRAY 16 OF LONGINT;
  6. Hash* = OBJECT (Hashes.Hash)
  7. VAR
  8. A, B, C, D: LONGINT; (* state *)
  9. N: LONGINT; (* total no of chars written *)
  10. X: Buffer;
  11. cb: ARRAY 4 OF LONGINT;
  12. PROCEDURE & Init*;
  13. BEGIN
  14. SetNameAndSize( "md5", 16 );
  15. initialized := FALSE
  16. END Init;
  17. PROCEDURE Initialize*;
  18. BEGIN
  19. N := 0;
  20. (* Initialize chaining values *)
  21. A := LONGINT( 067452301H );
  22. B := LONGINT( 0EFCDAB89H );
  23. C := LONGINT( 098BADCFEH );
  24. D := LONGINT( 010325476H );
  25. initialized := TRUE
  26. END Initialize;
  27. PROCEDURE Write( ch: CHAR );
  28. VAR i: LONGINT;
  29. BEGIN
  30. i := N MOD 4; cb[i] := ORD( ch );
  31. IF i = 3 THEN
  32. X[N DIV 4 MOD 16] := ((cb[3]*256 + cb[2])*256 + cb[1])*256 + cb[0]
  33. END;
  34. INC( N );
  35. IF N MOD 64 = 0 THEN MD5( X, A, B, C, D ) END;
  36. END Write;
  37. (** data: value to be hashed *)
  38. PROCEDURE Update*( CONST data: ARRAY OF CHAR; pos, len: LONGINT );
  39. VAR i: LONGINT;
  40. BEGIN
  41. ASSERT( initialized );
  42. FOR i := pos TO pos + len - 1 DO
  43. (* The following code equals ' Write(data[i]) '. It was copied here for better performance *)
  44. cb[ N MOD 4 ] := ORD( data[ i ] );
  45. IF N MOD 4 = 3 THEN
  46. X[ N DIV 4 MOD 16 ] := ( ( cb[3]*256 + cb[2] )*256 + cb[1] )*256 + cb[0]
  47. END;
  48. INC( N );
  49. IF N MOD 64 = 0 THEN MD5( X, A, B, C, D ) END;
  50. END
  51. END Update;
  52. (** get the hashvalue of length SELF.size *)
  53. PROCEDURE GetHash*( VAR buf: ARRAY OF CHAR; pos: LONGINT );
  54. VAR n: LONGINT;
  55. BEGIN
  56. (* Append padding *)
  57. n := N*8;
  58. Write( 80X ); (* 1000 0000 *)
  59. WHILE N MOD 64 # 56 DO
  60. Write( 0X ) (* 0000 0000 *)
  61. END;
  62. (* 64-bit representation of b mod 2^64 *)
  63. Write( CHR( n MOD 256 ) ); n := n DIV 256;
  64. Write( CHR( n MOD 256 ) ); n := n DIV 256;
  65. Write( CHR( n MOD 256 ) ); n := n DIV 256;
  66. Write( CHR( n MOD 256 ) );
  67. Write( 0X ); Write( 0X ); Write( 0X ); Write( 0X );
  68. U.IntToBufferLE( A, buf, pos ); U.IntToBufferLE( B, buf, pos + 4 );
  69. U.IntToBufferLE( C, buf, pos + 8); U.IntToBufferLE( D, buf, pos + 12 );
  70. END GetHash;
  71. END Hash;
  72. (*-----------------------------------------------------------------------------------*)
  73. VAR
  74. T: ARRAY 65 OF LONGINT;
  75. (** get an instance of MD5 *)
  76. PROCEDURE NewHash*( ) : Hashes.Hash;
  77. VAR h: Hash;
  78. BEGIN
  79. NEW( h ); RETURN h
  80. END NewHash;
  81. PROCEDURE MD5( CONST X: Buffer; VAR A, B, C, D: LONGINT );
  82. VAR a, b, c, d: LONGINT;
  83. PROCEDURE -F1( VAR a: LONGINT; b, c, d, x, s, t: LONGINT );
  84. VAR f: LONGINT;
  85. BEGIN
  86. f := S.VAL( LONGINT, (S.VAL( SET32, b ) * S.VAL( SET32, c )) + ((-S.VAL( SET32, b )) * S.VAL( SET32, d )) );
  87. a := ROT( a + f + x + t, s ) + b
  88. END F1;
  89. PROCEDURE -F2( VAR a: LONGINT; b, c, d, x, s, t: LONGINT );
  90. VAR f: LONGINT;
  91. BEGIN
  92. f := S.VAL( LONGINT, (S.VAL( SET32, b ) * S.VAL( SET32, d )) + (S.VAL( SET32, c ) * (-S.VAL( SET32, d ))) );
  93. a := ROT( a + f + x + t, s ) + b
  94. END F2;
  95. PROCEDURE -F3( VAR a: LONGINT; b, c, d, x, s, t: LONGINT );
  96. VAR f: LONGINT;
  97. BEGIN
  98. f := S.VAL( LONGINT, S.VAL( SET32, b ) / S.VAL( SET32, c ) / S.VAL( SET32, d ) );
  99. a := ROT( a + f + x + t, s ) + b
  100. END F3;
  101. PROCEDURE -F4( VAR a: LONGINT; b, c, d, x, s, t: LONGINT );
  102. VAR f: LONGINT;
  103. BEGIN
  104. f := S.VAL( LONGINT, S.VAL( SET32, c ) / (S.VAL( SET32, b ) + (-S.VAL( SET32, d ))) );
  105. a := ROT( a + f + x + t, s ) + b
  106. END F4;
  107. BEGIN
  108. a := A; b := B; c := C; d := D;
  109. F1( a, b, c, d, X[00], 07, T[01] ); F1( d, a, b, c, X[01], 12, T[02] );
  110. F1( c, d, a, b, X[02], 17, T[03] ); F1( b, c, d, a, X[03], 22, T[04] );
  111. F1( a, b, c, d, X[04], 07, T[05] ); F1( d, a, b, c, X[05], 12, T[06] );
  112. F1( c, d, a, b, X[06], 17, T[07] ); F1( b, c, d, a, X[07], 22, T[08] );
  113. F1( a, b, c, d, X[08], 07, T[09] ); F1( d, a, b, c, X[09], 12, T[10] );
  114. F1( c, d, a, b, X[10], 17, T[11] ); F1( b, c, d, a, X[11], 22, T[12] );
  115. F1( a, b, c, d, X[12], 07, T[13] ); F1( d, a, b, c, X[13], 12, T[14] );
  116. F1( c, d, a, b, X[14], 17, T[15] ); F1( b, c, d, a, X[15], 22, T[16] );
  117. F2( a, b, c, d, X[01], 05, T[17] ); F2( d, a, b, c, X[06], 09, T[18] );
  118. F2( c, d, a, b, X[11], 14, T[19] ); F2( b, c, d, a, X[00], 20, T[20] );
  119. F2( a, b, c, d, X[05], 05, T[21] ); F2( d, a, b, c, X[10], 09, T[22] );
  120. F2( c, d, a, b, X[15], 14, T[23] ); F2( b, c, d, a, X[04], 20, T[24] );
  121. F2( a, b, c, d, X[09], 05, T[25] ); F2( d, a, b, c, X[14], 09, T[26] );
  122. F2( c, d, a, b, X[03], 14, T[27] ); F2( b, c, d, a, X[08], 20, T[28] );
  123. F2( a, b, c, d, X[13], 05, T[29] ); F2( d, a, b, c, X[02], 09, T[30] );
  124. F2( c, d, a, b, X[07], 14, T[31] ); F2( b, c, d, a, X[12], 20, T[32] );
  125. F3( a, b, c, d, X[05], 04, T[33] ); F3( d, a, b, c, X[08], 11, T[34] );
  126. F3( c, d, a, b, X[11], 16, T[35] ); F3( b, c, d, a, X[14], 23, T[36] );
  127. F3( a, b, c, d, X[01], 04, T[37] ); F3( d, a, b, c, X[04], 11, T[38] );
  128. F3( c, d, a, b, X[07], 16, T[39] ); F3( b, c, d, a, X[10], 23, T[40] );
  129. F3( a, b, c, d, X[13], 04, T[41] ); F3( d, a, b, c, X[00], 11, T[42] );
  130. F3( c, d, a, b, X[03], 16, T[43] ); F3( b, c, d, a, X[06], 23, T[44] );
  131. F3( a, b, c, d, X[09], 04, T[45] ); F3( d, a, b, c, X[12], 11, T[46] );
  132. F3( c, d, a, b, X[15], 16, T[47] ); F3( b, c, d, a, X[02], 23, T[48] );
  133. F4( a, b, c, d, X[00], 06, T[49] ); F4( d, a, b, c, X[07], 10, T[50] );
  134. F4( c, d, a, b, X[14], 15, T[51] ); F4( b, c, d, a, X[05], 21, T[52] );
  135. F4( a, b, c, d, X[12], 06, T[53] ); F4( d, a, b, c, X[03], 10, T[54] );
  136. F4( c, d, a, b, X[10], 15, T[55] ); F4( b, c, d, a, X[01], 21, T[56] );
  137. F4( a, b, c, d, X[08], 06, T[57] ); F4( d, a, b, c, X[15], 10, T[58] );
  138. F4( c, d, a, b, X[06], 15, T[59] ); F4( b, c, d, a, X[13], 21, T[60] );
  139. F4( a, b, c, d, X[04], 06, T[61] ); F4( d, a, b, c, X[11], 10, T[62] );
  140. F4( c, d, a, b, X[02], 15, T[63] ); F4( b, c, d, a, X[09], 21, T[64] );
  141. INC( A, a ); INC( B, b ); INC( C, c ); INC( D, d );
  142. END MD5;
  143. PROCEDURE Initialize;
  144. VAR
  145. buf: U.InitBuffer; i: LONGINT;
  146. BEGIN
  147. NEW( buf, 1024 );
  148. buf.Add( "D76AA478 E8C7B756 242070DB C1BDCEEE F57C0FAF 4787C62A A8304613 FD469501");
  149. buf.Add( "698098D8 8B44F7AF FFFF5BB1 895CD7BE 6B901122 FD987193 A679438E 49B40821");
  150. buf.Add( "F61E2562 C040B340 265E5A51 E9B6C7AA D62F105D 02441453 D8A1E681 E7D3FBC8");
  151. buf.Add( "21E1CDE6 C33707D6 F4D50D87 455A14ED A9E3E905 FCEFA3F8 676F02D9 8D2A4C8A");
  152. buf.Add( "FFFA3942 8771F681 6D9D6122 FDE5380C A4BEEA44 4BDECFA9 F6BB4B60 BEBFBC70");
  153. buf.Add( "289B7EC6 EAA127FA D4EF3085 04881D05 D9D4D039 E6DB99E5 1FA27CF8 C4AC5665");
  154. buf.Add( "F4292244 432AFF97 AB9423A7 FC93A039 655B59C3 8F0CCC92 FFEFF47D 85845DD1");
  155. buf.Add( "6FA87E4F FE2CE6E0 A3014314 4E0811A1 F7537E82 BD3AF235 2AD7D2BB EB86D391");
  156. FOR i := 1 TO 64 DO T[i] := buf.GetInt() END
  157. END Initialize;
  158. BEGIN
  159. Initialize
  160. END CryptoMD5.