2005年11月24日13:30:09

MD5算法

MD5算法的delphi程序源代码:

  1. // tabs = 2
  2. // -------------------------------
  3. //
  4. //         MD5 Message-Digest for Delphi 4
  5. //
  6. //         Delphi 4 Unit implementing the
  7. //          RSA Data Security, Inc. MD5 Message-Digest Algorithm
  8. //
  9. //          Implementation of Ronald L. Rivest's RFC 1321
  10. //
  11. //          Copyright ?1997-1999 Medienagentur Fichtner & Meyer
  12. //          Written by Matthias Fichtner
  13. //
  14. // -------------------------------
  15. //       See RFC 1321 for RSA Data Security's copyright and license notice!
  16. // -------------------------------
  17. //<!--more-->
  18. //     14-Jun-97  mf  Implemented MD5 according to RFC 1321       RFC 1321
  19. //     16-Jun-97  mf  Initial release of the compiled unit (no source code)       RFC 1321
  20. //     28-Feb-99  mf  Added MD5Match function for comparing two digests       RFC 1321
  21. //     13-Sep-99  mf  Reworked the entire unit        RFC 1321
  22. //     17-Sep-99  mf  Reworked the "Test Driver" project          RFC 1321
  23. //     19-Sep-99  mf  Release of sources for MD5 unit and "Test Driver" project       RFC 1321
  24. //
  25. // -------------------------------
  26. //       The latest release of md5.pas will always be available from
  27. //          the distribution site at: http://www.fichtner.net/delphi/md5/
  28. // -------------------------------
  29. //       Please send questions, bug reports and suggestions
  30. //          regarding this code to: mfichtner@fichtner-meyer.com
  31. // -------------------------------
  32. //        This code is provided "as is" without express or
  33. //         implied warranty of any kind. Use it at your own risk.
  34. // -------------------------------
  35. unit md5;
  36. // -------------------------------
  37. INTERFACE
  38. // -------------------------------
  39. uses
  40. Windows;
  41. type
  42. MD5Count = array[0..1] of DWORD;
  43. MD5State = array[0..3] of DWORD;
  44. MD5Block = array[0..15] of DWORD;
  45. MD5CBits = array[0..7] of byte;
  46. MD5Digest = array[0..15] of byte;
  47. MD5Buffer = array[0..63] of byte;
  48. MD5Context = record
  49. State: MD5State;
  50. Count: MD5Count;
  51. Buffer: MD5Buffer;
  52. end;
  53. procedure MD5Init(var Context: MD5Context);
  54. procedure MD5Update(var Context: MD5Context; Input: pChar; Length: longword);
  55. procedure MD5Final(var Context: MD5Context; var Digest: MD5Digest);
  56. function MD5String(M: string): MD5Digest;
  57. function MD5File(N: string): MD5Digest;
  58. function MD5Print(D: MD5Digest): string;
  59. function MD5Match(D1, D2: MD5Digest): boolean;
  60. // -------------------------------
  61. IMPLEMENTATION
  62. // -------------------------------
  63. var
  64. PADDING: MD5Buffer = (
  65. $80, $00, $00, $00, $00, $00, $00, $00,
  66. $00, $00, $00, $00, $00, $00, $00, $00,
  67. $00, $00, $00, $00, $00, $00, $00, $00,
  68. $00, $00, $00, $00, $00, $00, $00, $00,
  69. $00, $00, $00, $00, $00, $00, $00, $00,
  70. $00, $00, $00, $00, $00, $00, $00, $00,
  71. $00, $00, $00, $00, $00, $00, $00, $00,
  72. $00, $00, $00, $00, $00, $00, $00, $00
  73. );
  74. function F(x, y, z: DWORD): DWORD;
  75. begin
  76. Result := (x and y) or ((not x) and z);
  77. end;
  78. function G(x, y, z: DWORD): DWORD;
  79. begin
  80. Result := (x and z) or (y and (not z));
  81. end;
  82. function H(x, y, z: DWORD): DWORD;
  83. begin
  84. Result := x xor y xor z;
  85. end;
  86. function I(x, y, z: DWORD): DWORD;
  87. begin
  88. Result := y xor (x or (not z));
  89. end;
  90. procedure rot(var x: DWORD; n: BYTE);
  91. begin
  92. x := (x shl n) or (x shr (32 - n));
  93. end;
  94. procedure FF(var a: DWORD; b, c, d, x: DWORD; s: BYTE; ac: DWORD);
  95. begin
  96. inc(a, F(b, c, d) + x + ac);
  97. rot(a, s);
  98. inc(a, b);
  99. end;
  100. procedure GG(var a: DWORD; b, c, d, x: DWORD; s: BYTE; ac: DWORD);
  101. begin
  102. inc(a, G(b, c, d) + x + ac);
  103. rot(a, s);
  104. inc(a, b);
  105. end;
  106. procedure HH(var a: DWORD; b, c, d, x: DWORD; s: BYTE; ac: DWORD);
  107. begin
  108. inc(a, H(b, c, d) + x + ac);
  109. rot(a, s);
  110. inc(a, b);
  111. end;
  112. procedure II(var a: DWORD; b, c, d, x: DWORD; s: BYTE; ac: DWORD);
  113. begin
  114. inc(a, I(b, c, d) + x + ac);
  115. rot(a, s);
  116. inc(a, b);
  117. end;
  118. // -------------------------------
  119. // Encode Count bytes at Source into (Count / 4) DWORDs at Target
  120. procedure Encode(Source, Target: pointer; Count: longword);
  121. var
  122. S: PByte;
  123. T: PDWORD;
  124. I: longword;
  125. begin
  126. S := Source;
  127. T := Target;
  128. for I := 1 to Count div 4 do begin
  129. T^ := S^;
  130. inc(S);
  131. T^ := T^ or (S^ shl 8);
  132. inc(S);
  133. T^ := T^ or (S^ shl 16);
  134. inc(S);
  135. T^ := T^ or (S^ shl 24);
  136. inc(S);
  137. inc(T);
  138. end;
  139. end;
  140. // Decode Count DWORDs at Source into (Count * 4) Bytes at Target
  141. procedure Decode(Source, Target: pointer; Count: longword);
  142. var
  143. S: PDWORD;
  144. T: PByte;
  145. I: longword;
  146. begin
  147. S := Source;
  148. T := Target;
  149. for I := 1 to Count do begin
  150. T^ := S^ and $ff;
  151. inc(T);
  152. T^ := (S^ shr 8) and $ff;
  153. inc(T);
  154. T^ := (S^ shr 16) and $ff;
  155. inc(T);
  156. T^ := (S^ shr 24) and $ff;
  157. inc(T);
  158. inc(S);
  159. end;
  160. end;
  161. // Transform State according to first 64 bytes at Buffer
  162. procedure Transform(Buffer: pointer; var State: MD5State);
  163. var
  164. a, b, c, d: DWORD;
  165. Block: MD5Block;
  166. begin
  167. Encode(Buffer, @Block, 64);
  168. a := State[0];
  169. b := State[1];
  170. c := State[2];
  171. d := State[3];
  172. FF (a, b, c, d, Block[ 0],  7, $d76aa478);
  173. FF (d, a, b, c, Block[ 1], 12, $e8c7b756);
  174. FF (c, d, a, b, Block[ 2], 17, $242070db);
  175. FF (b, c, d, a, Block[ 3], 22, $c1bdceee);
  176. FF (a, b, c, d, Block[ 4],  7, $f57c0faf);
  177. FF (d, a, b, c, Block[ 5], 12, $4787c62a);
  178. FF (c, d, a, b, Block[ 6], 17, $a8304613);
  179. FF (b, c, d, a, Block[ 7], 22, $fd469501);
  180. FF (a, b, c, d, Block[ 8],  7, $698098d8);
  181. FF (d, a, b, c, Block[ 9], 12, $8b44f7af);
  182. FF (c, d, a, b, Block[10], 17, $ffff5bb1);
  183. FF (b, c, d, a, Block[11], 22, $895cd7be);
  184. FF (a, b, c, d, Block[12],  7, $6b901122);
  185. FF (d, a, b, c, Block[13], 12, $fd987193);
  186. FF (c, d, a, b, Block[14], 17, $a679438e);
  187. FF (b, c, d, a, Block[15], 22, $49b40821);
  188. GG (a, b, c, d, Block[ 1],  5, $f61e2562);
  189. GG (d, a, b, c, Block[ 6],  9, $c040b340);
  190. GG (c, d, a, b, Block[11], 14, $265e5a51);
  191. GG (b, c, d, a, Block[ 0], 20, $e9b6c7aa);
  192. GG (a, b, c, d, Block[ 5],  5, $d62f105d);
  193. GG (d, a, b, c, Block[10],  9,  $2441453);
  194. GG (c, d, a, b, Block[15], 14, $d8a1e681);
  195. GG (b, c, d, a, Block[ 4], 20, $e7d3fbc8);
  196. GG (a, b, c, d, Block[ 9],  5, $21e1cde6);
  197. GG (d, a, b, c, Block[14],  9, $c33707d6);
  198. GG (c, d, a, b, Block[ 3], 14, $f4d50d87);
  199. GG (b, c, d, a, Block[ 8], 20, $455a14ed);
  200. GG (a, b, c, d, Block[13],  5, $a9e3e905);
  201. GG (d, a, b, c, Block[ 2],  9, $fcefa3f8);
  202. GG (c, d, a, b, Block[ 7], 14, $676f02d9);
  203. GG (b, c, d, a, Block[12], 20, $8d2a4c8a);
  204. HH (a, b, c, d, Block[ 5],  4, $fffa3942);
  205. HH (d, a, b, c, Block[ 8], 11, $8771f681);
  206. HH (c, d, a, b, Block[11], 16, $6d9d6122);
  207. HH (b, c, d, a, Block[14], 23, $fde5380c);
  208. HH (a, b, c, d, Block[ 1],  4, $a4beea44);
  209. HH (d, a, b, c, Block[ 4], 11, $4bdecfa9);
  210. HH (c, d, a, b, Block[ 7], 16, $f6bb4b60);
  211. HH (b, c, d, a, Block[10], 23, $bebfbc70);
  212. HH (a, b, c, d, Block[13],  4, $289b7ec6);
  213. HH (d, a, b, c, Block[ 0], 11, $eaa127fa);
  214. HH (c, d, a, b, Block[ 3], 16, $d4ef3085);
  215. HH (b, c, d, a, Block[ 6], 23,  $4881d05);
  216. HH (a, b, c, d, Block[ 9],  4, $d9d4d039);
  217. HH (d, a, b, c, Block[12], 11, $e6db99e5);
  218. HH (c, d, a, b, Block[15], 16, $1fa27cf8);
  219. HH (b, c, d, a, Block[ 2], 23, $c4ac5665);
  220. II (a, b, c, d, Block[ 0],  6, $f4292244);
  221. II (d, a, b, c, Block[ 7], 10, $432aff97);
  222. II (c, d, a, b, Block[14], 15, $ab9423a7);
  223. II (b, c, d, a, Block[ 5], 21, $fc93a039);
  224. II (a, b, c, d, Block[12],  6, $655b59c3);
  225. II (d, a, b, c, Block[ 3], 10, $8f0ccc92);
  226. II (c, d, a, b, Block[10], 15, $ffeff47d);
  227. II (b, c, d, a, Block[ 1], 21, $85845dd1);
  228. II (a, b, c, d, Block[ 8],  6, $6fa87e4f);
  229. II (d, a, b, c, Block[15], 10, $fe2ce6e0);
  230. II (c, d, a, b, Block[ 6], 15, $a3014314);
  231. II (b, c, d, a, Block[13], 21, $4e0811a1);
  232. II (a, b, c, d, Block[ 4],  6, $f7537e82);
  233. II (d, a, b, c, Block[11], 10, $bd3af235);
  234. II (c, d, a, b, Block[ 2], 15, $2ad7d2bb);
  235. II (b, c, d, a, Block[ 9], 21, $eb86d391);
  236. inc(State[0], a);
  237. inc(State[1], b);
  238. inc(State[2], c);
  239. inc(State[3], d);
  240. end;
  241. // -------------------------------
  242. // Initialize given Context
  243. procedure MD5Init(var Context: MD5Context);
  244. begin
  245. with Context do begin
  246. State[0] := $67452301;
  247. State[1] := $efcdab89;
  248. State[2] := $98badcfe;
  249. State[3] := $10325476;
  250. Count[0] := 0;
  251. Count[1] := 0;
  252. ZeroMemory(@Buffer, SizeOf(MD5Buffer));
  253. end;
  254. end;
  255. // Update given Context to include Length bytes of Input
  256. procedure MD5Update(var Context: MD5Context; Input: pChar; Length: longword);
  257. var
  258. Index: longword;
  259. PartLen: longword;
  260. I: longword;
  261. begin
  262. with Context do begin
  263. Index := (Count[0] shr 3) and $3f;
  264. inc(Count[0], Length shl 3);
  265. if Count[0] < (Length shl 3) then inc(Count[1]);
  266. inc(Count[1], Length shr 29);
  267. end;
  268. PartLen := 64 - Index;
  269. if Length >= PartLen then begin
  270. CopyMemory(@Context.Buffer[Index], Input, PartLen);
  271. Transform(@Context.Buffer, Context.State);
  272. I := PartLen;
  273. while I + 63 < Length do begin
  274. Transform(@Input[I], Context.State);
  275. inc(I, 64);
  276. end;
  277. Index := 0;
  278. end else I := 0;
  279. CopyMemory(@Context.Buffer[Index], @Input[I], Length - I);
  280. end;
  281. // Finalize given Context, create Digest and zeroize Context
  282. procedure MD5Final(var Context: MD5Context; var Digest: MD5Digest);
  283. var
  284. Bits: MD5CBits;
  285. Index: longword;
  286. PadLen: longword;
  287. begin
  288. Decode(@Context.Count, @Bits, 2);
  289. Index := (Context.Count[0] shr 3) and $3f;
  290. if Index < 56 then PadLen := 56 - Index else PadLen := 120 - Index;
  291. MD5Update(Context, @PADDING, PadLen);
  292. MD5Update(Context, @Bits, 8);
  293. Decode(@Context.State, @Digest, 4);
  294. ZeroMemory(@Context, SizeOf(MD5Context));
  295. end;
  296. // -------------------------------
  297. // Create digest of given Message
  298. function MD5String(M: string): MD5Digest;
  299. var
  300. Context: MD5Context;
  301. begin
  302. MD5Init(Context);
  303. MD5Update(Context, pChar(M), length(M));
  304. MD5Final(Context, Result);
  305. end;
  306. // Create digest of file with given Name
  307. function MD5File(N: string): MD5Digest;
  308. var
  309. FileHandle: THandle;
  310. MapHandle: THandle;
  311. ViewPointer: pointer;
  312. Context: MD5Context;
  313. begin
  314. MD5Init(Context);
  315. FileHandle := CreateFile(pChar(N), GENERIC_READ, FILE_SHARE_READ or FILE_SHARE_WRITE,
  316. nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL or FILE_FLAG_SEQUENTIAL_SCAN, 0);
  317. if FileHandle <> INVALID_HANDLE_VALUE then try
  318. MapHandle := CreateFileMapping(FileHandle, nil, PAGE_READONLY, 0, 0, nil);
  319. if MapHandle <> 0 then try
  320. ViewPointer := MapViewOfFile(MapHandle, FILE_MAP_READ, 0, 0, 0);
  321. if ViewPointer <> nil then try
  322. MD5Update(Context, ViewPointer, GetFileSize(FileHandle, nil));
  323. finally
  324. UnmapViewOfFile(ViewPointer);
  325. end;
  326. finally
  327. CloseHandle(MapHandle);
  328. end;
  329. finally
  330. CloseHandle(FileHandle);
  331. end;
  332. MD5Final(Context, Result);
  333. end;
  334. // Create hex representation of given Digest
  335. function MD5Print(D: MD5Digest): string;
  336. var
  337. I: byte;
  338. const
  339. Digits: array[0..15] of char =
  340. ('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f');
  341. begin
  342. Result := '';
  343. for I := 0 to 15 do Result := Result + Digits[(D[I] shr 4) and $0f] + Digits[D[I] and $0f];
  344. end;
  345. // -------------------------------
  346. // Compare two Digests
  347. function MD5Match(D1, D2: MD5Digest): boolean;
  348. var
  349. I: byte;
  350. begin
  351. I := 0;
  352. Result := TRUE;
  353. while Result and (I < 16) do begin
  354. Result := D1[I] = D2[I];
  355. inc(I);
  356. end;
  357. end;
  358. end.

本文共有 1 条评论MD5算法


  1. Gravatar 1 Anonymous 2006-6-25 3:41

    LUOK,O,SONG BSDYDNS

请留下您的评论:

您可以使用以下XHTML代码: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <code> <em> <i> <strike> <strong>