Advertisement
Guest User

hash

a guest
Aug 27th, 2012
307
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 12.44 KB | None | 0 0
  1. { **** UBPFD *********** by delphibase.endimus.com ****
  2. >> Вычисление хеш-суммы MD5
  3.  
  4. Зависимости: Windows, SysUtils, Classes
  5. Автор: Dimka Maslov, mainbox@endimus.ru, ICQ:148442121, Санкт-Петербург
  6. Copyright: http://www.faqs.org/rfcs/rfc1321.html
  7. Дата: 19 июня 2002 г.
  8. ***************************************************** }
  9.  
  10. {******************************************************************}
  11. { MD5 Hashsum Evaluation Unit For Borland Delphi }
  12. { }
  13. { Copyright © 2002 by Dimka Maslov }
  14. { E-mail: mainbox@endimus.com, }
  15. { Web-site: http://www.endimus.com }
  16. { }
  17. { Derived from the RSA Data Security, Inc. }
  18. { MD5 Message-Digest Algorithm described in RFC 1321 }
  19. { http://www.faqs.org/rfcs/rfc1321.html }
  20. {******************************************************************}
  21.  
  22. unit md5;
  23.  
  24. interface
  25.  
  26. uses Windows, SysUtils, Classes;
  27.  
  28. type
  29. { Тип TMD5Digest используется для получения
  30. результата функций вычисления хеш-суммы.
  31. Содержимое записи можно использовать
  32. как набор из 4 целых чисел, или как
  33. массив из 16 байт }
  34. PMD5Digest = ^TMD5Digest;
  35. TMD5Digest = record
  36. case Integer of
  37. 0: (A, B, C, D: LongInt);
  38. 1: (v: array[0..15] of Byte);
  39. end;
  40.  
  41. // вычисление хеш-суммы для строки
  42. function MD5String(const S: string): TMD5Digest;
  43.  
  44. // вычисление хеш-суммы для файла
  45. function MD5File(const FileName: string): TMD5Digest;
  46.  
  47. // вычисление хеш-суммы для содержиого потока Stream
  48. function MD5Stream(const Stream: TStream): TMD5Digest;
  49.  
  50. // вычисление хеш-суммы для произвольного буфера
  51. function MD5Buffer(const Buffer; Size: Integer): TMD5Digest;
  52.  
  53. // преобразование хеш-суммы в строку из шестнадцатеричных цифр
  54. function MD5DigestToStr(const Digest: TMD5Digest): string;
  55.  
  56. // сравнение двух хеш-сумм
  57. function MD5DigestCompare(const Digest1, Digest2: TMD5Digest): Boolean;
  58.  
  59. implementation
  60.  
  61. {
  62. Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
  63. rights reserved.
  64.  
  65. License to copy and use this software is granted provided that it
  66. is identified as the "RSA Data Security, Inc. MD5 Message-Digest
  67. Algorithm" in all material mentioning or referencing this software
  68. or this function.
  69.  
  70. License is also granted to make and use derivative works provided
  71. that such works are identified as "derived from the RSA Data
  72. Security, Inc. MD5 Message-Digest Algorithm" in all material
  73. mentioning or referencing the derived work.
  74.  
  75. RSA Data Security, Inc. makes no representations concerning either
  76. the merchantability of this software or the suitability of this
  77. software for any particular purpose. It is provided "as is"
  78. without express or implied warranty of any kind.
  79.  
  80. These notices must be retained in any copies of any part of this
  81. documentation and/or software.
  82. }
  83.  
  84. type
  85. UINT4 = LongWord;
  86.  
  87. PArray4UINT4 = ^TArray4UINT4;
  88. TArray4UINT4 = array[0..3] of UINT4;
  89. PArray2UINT4 = ^TArray2UINT4;
  90. TArray2UINT4 = array[0..1] of UINT4;
  91. PArray16Byte = ^TArray16Byte;
  92. TArray16Byte = array[0..15] of Byte;
  93. PArray64Byte = ^TArray64Byte;
  94. TArray64Byte = array[0..63] of Byte;
  95.  
  96. PByteArray = ^TByteArray;
  97. TByteArray = array[0..0] of Byte;
  98.  
  99. PUINT4Array = ^TUINT4Array;
  100. TUINT4Array = array[0..0] of UINT4;
  101.  
  102. PMD5Context = ^TMD5Context;
  103. TMD5Context = record
  104. state: TArray4UINT4;
  105. count: TArray2UINT4;
  106. buffer: TArray64Byte;
  107. end;
  108.  
  109. const
  110. S11 = 7;
  111. S12 = 12;
  112. S13 = 17;
  113. S14 = 22;
  114. S21 = 5;
  115. S22 = 9;
  116. S23 = 14;
  117. S24 = 20;
  118. S31 = 4;
  119. S32 = 11;
  120. S33 = 16;
  121. S34 = 23;
  122. S41 = 6;
  123. S42 = 10;
  124. S43 = 15;
  125. S44 = 21;
  126.  
  127. var
  128. Padding: TArray64Byte =
  129. ($80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  130. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  131. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
  132.  
  133. function _F(x, y, z: UINT4): UINT4;
  134. begin
  135. Result := (((x) and (y)) or ((not x) and (z)));
  136. end;
  137.  
  138. function _G(x, y, z: UINT4): UINT4;
  139. begin
  140. Result := (((x) and (z)) or ((y) and (not z)));
  141. end;
  142.  
  143. function _H(x, y, z: UINT4): UINT4;
  144. begin
  145. Result := ((x) xor (y) xor (z));
  146. end;
  147.  
  148. function _I(x, y, z: UINT4): UINT4;
  149. begin
  150. Result := ((y) xor ((x) or (not z)));
  151. end;
  152.  
  153. function ROTATE_LEFT(x, n: UINT4): UINT4;
  154. begin
  155. Result := (((x) shl (n)) or ((x) shr (32 - (n))));
  156. end;
  157.  
  158. procedure FF(var a: UINT4; b, c, d, x, s, ac: UINT4);
  159. begin
  160. a := a + _F(b, c, d) + x + ac;
  161. a := ROTATE_LEFT(a, s);
  162. a := a + b;
  163. end;
  164.  
  165. procedure GG(var a: UINT4; b, c, d, x, s, ac: UINT4);
  166. begin
  167. a := a + _G(b, c, d) + x + ac;
  168. a := ROTATE_LEFT(a, s);
  169. a := a + b;
  170. end;
  171.  
  172. procedure HH(var a: UINT4; b, c, d, x, s, ac: UINT4);
  173. begin
  174. a := a + _H(b, c, d) + x + ac;
  175. a := ROTATE_LEFT(a, s);
  176. a := a + b;
  177. end;
  178.  
  179. procedure II(var a: UINT4; b, c, d, x, s, ac: UINT4);
  180. begin
  181. a := a + _I(b, c, d) + x + ac;
  182. a := ROTATE_LEFT(a, s);
  183. a := a + b;
  184. end;
  185.  
  186. procedure MD5Encode(Output: PByteArray; Input: PUINT4Array; Len: LongWord);
  187. var
  188. i, j: LongWord;
  189. begin
  190. j := 0;
  191. i := 0;
  192. while j < Len do
  193. begin
  194. output[j] := Byte(input[i] and $FF);
  195. output[j + 1] := Byte((input[i] shr 8) and $FF);
  196. output[j + 2] := Byte((input[i] shr 16) and $FF);
  197. output[j + 3] := Byte((input[i] shr 24) and $FF);
  198. Inc(j, 4);
  199. Inc(i);
  200. end;
  201. end;
  202.  
  203. procedure MD5Decode(Output: PUINT4Array; Input: PByteArray; Len: LongWord);
  204. var
  205. i, j: LongWord;
  206. begin
  207. j := 0;
  208. i := 0;
  209. while j < Len do
  210. begin
  211. Output[i] := UINT4(input[j]) or (UINT4(input[j + 1]) shl 8) or
  212. (UINT4(input[j + 2]) shl 16) or (UINT4(input[j + 3]) shl 24);
  213. Inc(j, 4);
  214. Inc(i);
  215. end;
  216. end;
  217.  
  218. procedure MD5_memcpy(Output: PByteArray; Input: PByteArray; Len: LongWord);
  219. begin
  220. Move(Input^, Output^, Len);
  221. end;
  222.  
  223. procedure MD5_memset(Output: PByteArray; Value: Integer; Len: LongWord);
  224. begin
  225. FillChar(Output^, Len, Byte(Value));
  226. end;
  227.  
  228. procedure MD5Transform(State: PArray4UINT4; Buffer: PArray64Byte);
  229. var
  230. a, b, c, d: UINT4;
  231. x: array[0..15] of UINT4;
  232. begin
  233. a := State[0];
  234. b := State[1];
  235. c := State[2];
  236. d := State[3];
  237. MD5Decode(PUINT4Array(@x), PByteArray(Buffer), 64);
  238.  
  239. FF(a, b, c, d, x[0], S11, $D76AA478);
  240. FF(d, a, b, c, x[1], S12, $E8C7B756);
  241. FF(c, d, a, b, x[2], S13, $242070DB);
  242. FF(b, c, d, a, x[3], S14, $C1BDCEEE);
  243. FF(a, b, c, d, x[4], S11, $F57C0FAF);
  244. FF(d, a, b, c, x[5], S12, $4787C62A);
  245. FF(c, d, a, b, x[6], S13, $A8304613);
  246. FF(b, c, d, a, x[7], S14, $FD469501);
  247. FF(a, b, c, d, x[8], S11, $698098D8);
  248. FF(d, a, b, c, x[9], S12, $8B44F7AF);
  249. FF(c, d, a, b, x[10], S13, $FFFF5BB1);
  250. FF(b, c, d, a, x[11], S14, $895CD7BE);
  251. FF(a, b, c, d, x[12], S11, $6B901122);
  252. FF(d, a, b, c, x[13], S12, $FD987193);
  253. FF(c, d, a, b, x[14], S13, $A679438E);
  254. FF(b, c, d, a, x[15], S14, $49B40821);
  255.  
  256. GG(a, b, c, d, x[1], S21, $F61E2562);
  257. GG(d, a, b, c, x[6], S22, $C040B340);
  258. GG(c, d, a, b, x[11], S23, $265E5A51);
  259. GG(b, c, d, a, x[0], S24, $E9B6C7AA);
  260. GG(a, b, c, d, x[5], S21, $D62F105D);
  261. GG(d, a, b, c, x[10], S22, $2441453);
  262. GG(c, d, a, b, x[15], S23, $D8A1E681);
  263. GG(b, c, d, a, x[4], S24, $E7D3FBC8);
  264. GG(a, b, c, d, x[9], S21, $21E1CDE6);
  265. GG(d, a, b, c, x[14], S22, $C33707D6);
  266. GG(c, d, a, b, x[3], S23, $F4D50D87);
  267.  
  268. GG(b, c, d, a, x[8], S24, $455A14ED);
  269. GG(a, b, c, d, x[13], S21, $A9E3E905);
  270. GG(d, a, b, c, x[2], S22, $FCEFA3F8);
  271. GG(c, d, a, b, x[7], S23, $676F02D9);
  272. GG(b, c, d, a, x[12], S24, $8D2A4C8A);
  273.  
  274. HH(a, b, c, d, x[5], S31, $FFFA3942);
  275. HH(d, a, b, c, x[8], S32, $8771F681);
  276. HH(c, d, a, b, x[11], S33, $6D9D6122);
  277. HH(b, c, d, a, x[14], S34, $FDE5380C);
  278. HH(a, b, c, d, x[1], S31, $A4BEEA44);
  279. HH(d, a, b, c, x[4], S32, $4BDECFA9);
  280. HH(c, d, a, b, x[7], S33, $F6BB4B60);
  281. HH(b, c, d, a, x[10], S34, $BEBFBC70);
  282. HH(a, b, c, d, x[13], S31, $289B7EC6);
  283. HH(d, a, b, c, x[0], S32, $EAA127FA);
  284. HH(c, d, a, b, x[3], S33, $D4EF3085);
  285. HH(b, c, d, a, x[6], S34, $4881D05);
  286. HH(a, b, c, d, x[9], S31, $D9D4D039);
  287. HH(d, a, b, c, x[12], S32, $E6DB99E5);
  288. HH(c, d, a, b, x[15], S33, $1FA27CF8);
  289. HH(b, c, d, a, x[2], S34, $C4AC5665);
  290.  
  291. II(a, b, c, d, x[0], S41, $F4292244);
  292. II(d, a, b, c, x[7], S42, $432AFF97);
  293. II(c, d, a, b, x[14], S43, $AB9423A7);
  294. II(b, c, d, a, x[5], S44, $FC93A039);
  295. II(a, b, c, d, x[12], S41, $655B59C3);
  296. II(d, a, b, c, x[3], S42, $8F0CCC92);
  297. II(c, d, a, b, x[10], S43, $FFEFF47D);
  298. II(b, c, d, a, x[1], S44, $85845DD1);
  299. II(a, b, c, d, x[8], S41, $6FA87E4F);
  300. II(d, a, b, c, x[15], S42, $FE2CE6E0);
  301. II(c, d, a, b, x[6], S43, $A3014314);
  302. II(b, c, d, a, x[13], S44, $4E0811A1);
  303. II(a, b, c, d, x[4], S41, $F7537E82);
  304. II(d, a, b, c, x[11], S42, $BD3AF235);
  305. II(c, d, a, b, x[2], S43, $2AD7D2BB);
  306. II(b, c, d, a, x[9], S44, $EB86D391);
  307.  
  308. Inc(State[0], a);
  309. Inc(State[1], b);
  310. Inc(State[2], c);
  311. Inc(State[3], d);
  312.  
  313. MD5_memset(PByteArray(@x), 0, SizeOf(x));
  314. end;
  315.  
  316. procedure MD5Init(var Context: TMD5Context);
  317. begin
  318. FillChar(Context, SizeOf(Context), 0);
  319. Context.state[0] := $67452301;
  320. Context.state[1] := $EFCDAB89;
  321. Context.state[2] := $98BADCFE;
  322. Context.state[3] := $10325476;
  323. end;
  324.  
  325. procedure MD5Update(var Context: TMD5Context; Input: PByteArray; InputLen:
  326. LongWord);
  327. var
  328. i, index, partLen: LongWord;
  329.  
  330. begin
  331. index := LongWord((context.count[0] shr 3) and $3F);
  332. Inc(Context.count[0], UINT4(InputLen) shl 3);
  333. if Context.count[0] < UINT4(InputLen) shl 3 then
  334. Inc(Context.count[1]);
  335. Inc(Context.count[1], UINT4(InputLen) shr 29);
  336. partLen := 64 - index;
  337. if inputLen >= partLen then
  338. begin
  339. MD5_memcpy(PByteArray(@Context.buffer[index]), Input, PartLen);
  340. MD5Transform(@Context.state, @Context.buffer);
  341. i := partLen;
  342. while i + 63 < inputLen do
  343. begin
  344. MD5Transform(@Context.state, PArray64Byte(@Input[i]));
  345. Inc(i, 64);
  346. end;
  347. index := 0;
  348. end
  349. else
  350. i := 0;
  351. MD5_memcpy(PByteArray(@Context.buffer[index]), PByteArray(@Input[i]), inputLen
  352. - i);
  353. end;
  354.  
  355. procedure MD5Final(var Digest: TMD5Digest; var Context: TMD5Context);
  356. var
  357. bits: array[0..7] of Byte;
  358. index, padLen: LongWord;
  359. begin
  360. MD5Encode(PByteArray(@bits), PUINT4Array(@Context.count), 8);
  361. index := LongWord((Context.count[0] shr 3) and $3F);
  362. if index < 56 then
  363. padLen := 56 - index
  364. else
  365. padLen := 120 - index;
  366. MD5Update(Context, PByteArray(@PADDING), padLen);
  367. MD5Update(Context, PByteArray(@Bits), 8);
  368. MD5Encode(PByteArray(@Digest), PUINT4Array(@Context.state), 16);
  369. MD5_memset(PByteArray(@Context), 0, SizeOf(Context));
  370. end;
  371.  
  372. function MD5DigestToStr(const Digest: TMD5Digest): string;
  373. var
  374. i: Integer;
  375. begin
  376. Result := '';
  377. for i := 0 to 15 do
  378. Result := Result + IntToHex(Digest.v[i], 2);
  379. end;
  380.  
  381. function MD5String(const S: string): TMD5Digest;
  382. begin
  383. Result := MD5Buffer(PChar(S)^, Length(S));
  384. end;
  385.  
  386. function MD5File(const FileName: string): TMD5Digest;
  387. var
  388. F: TFileStream;
  389. begin
  390. F := TFileStream.Create(FileName, fmOpenRead);
  391. try
  392. Result := MD5Stream(F);
  393. finally
  394. F.Free;
  395. end;
  396. end;
  397.  
  398. function MD5Stream(const Stream: TStream): TMD5Digest;
  399. var
  400. Context: TMD5Context;
  401. Buffer: array[0..4095] of Byte;
  402. Size: Integer;
  403. ReadBytes: Integer;
  404. TotalBytes: Integer;
  405. SavePos: Integer;
  406. begin
  407. MD5Init(Context);
  408. Size := Stream.Size;
  409. SavePos := Stream.Position;
  410. TotalBytes := 0;
  411. try
  412. Stream.Seek(0, soFromBeginning);
  413. repeat
  414. ReadBytes := Stream.Read(Buffer, SizeOf(Buffer));
  415. Inc(TotalBytes, ReadBytes);
  416. MD5Update(Context, @Buffer, ReadBytes);
  417. until (ReadBytes = 0) or (TotalBytes = Size);
  418. finally
  419. Stream.Seek(SavePos, soFromBeginning);
  420. end;
  421. MD5Final(Result, Context);
  422. end;
  423.  
  424. function MD5Buffer(const Buffer; Size: Integer): TMD5Digest;
  425. var
  426. Context: TMD5Context;
  427. begin
  428. MD5Init(Context);
  429. MD5Update(Context, PByteArray(@Buffer), Size);
  430. MD5Final(Result, Context);
  431. end;
  432.  
  433. function MD5DigestCompare(const Digest1, Digest2: TMD5Digest): Boolean;
  434. begin
  435. Result := False;
  436. if Digest1.A <> Digest2.A then
  437. Exit;
  438. if Digest1.B <> Digest2.B then
  439. Exit;
  440. if Digest1.C <> Digest2.C then
  441. Exit;
  442. if Digest1.D <> Digest2.D then
  443. Exit;
  444. Result := True;
  445. end;
  446.  
  447. end.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement