MD5CryptoServiceProvider.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495
  1. //
  2. // System.Security.Cryptography MD5CryptoServiceProvider Class implementation
  3. //
  4. // Authors:
  5. // Matthew S. Ford ([email protected])
  6. //
  7. // Copyright 2001 by Matthew S. Ford.
  8. //
  9. namespace System.Security.Cryptography {
  10. /// <summary>
  11. /// C# implementation of the MD5 cryptographic hash function.
  12. /// </summary>
  13. public class MD5CryptoServiceProvider : MD5 {
  14. private const int BLOCK_SIZE_BYTES = 64;
  15. private const int HASH_SIZE_BYTES = 16;
  16. private const int HASH_SIZE_BITS = 128;
  17. [CLSCompliant(false)] private uint[] _H;
  18. [CLSCompliant(false)] private uint count;
  19. private byte[] _ProcessingBuffer; // Used to start data when passed less than a block worth.
  20. private int _ProcessingBufferCount; // Counts how much data we have stored that still needs processed.
  21. /// <summary>
  22. /// Creates a new MD5CryptoServiceProvider.
  23. /// </summary>
  24. public MD5CryptoServiceProvider ()
  25. {
  26. _H = new uint[4];
  27. HashSizeValue = HASH_SIZE_BITS;
  28. _ProcessingBuffer = new byte[BLOCK_SIZE_BYTES];
  29. Initialize();
  30. }
  31. ~MD5CryptoServiceProvider ()
  32. {
  33. Dispose (false);
  34. }
  35. protected override void Dispose (bool disposing)
  36. {
  37. // nothing to do (managed implementation)
  38. }
  39. /// <summary>
  40. /// Drives the hashing function.
  41. /// </summary>
  42. /// <param name="rgb">Byte array containing the data to hash.</param>
  43. /// <param name="start">Where in the input buffer to start.</param>
  44. /// <param name="size">Size in bytes of the data in the buffer to hash.</param>
  45. protected override void HashCore (byte[] rgb, int start, int size)
  46. {
  47. int i;
  48. State = 1;
  49. if (_ProcessingBufferCount != 0) {
  50. if (size < (BLOCK_SIZE_BYTES - _ProcessingBufferCount)) {
  51. System.Buffer.BlockCopy (rgb, start, _ProcessingBuffer, _ProcessingBufferCount, size);
  52. _ProcessingBufferCount += size;
  53. return;
  54. }
  55. else {
  56. i = (BLOCK_SIZE_BYTES - _ProcessingBufferCount);
  57. System.Buffer.BlockCopy (rgb, start, _ProcessingBuffer, _ProcessingBufferCount, i);
  58. ProcessBlock (_ProcessingBuffer, 0);
  59. _ProcessingBufferCount = 0;
  60. start += i;
  61. size -= i;
  62. }
  63. }
  64. for (i=0; i<size-size%BLOCK_SIZE_BYTES; i += BLOCK_SIZE_BYTES) {
  65. ProcessBlock (rgb, start+i);
  66. }
  67. if (size%BLOCK_SIZE_BYTES != 0) {
  68. System.Buffer.BlockCopy (rgb, size-size%BLOCK_SIZE_BYTES+start, _ProcessingBuffer, 0, size%BLOCK_SIZE_BYTES);
  69. _ProcessingBufferCount = size%BLOCK_SIZE_BYTES;
  70. }
  71. }
  72. /// <summary>
  73. /// This finalizes the hash. Takes the data from the chaining variables and returns it.
  74. /// </summary>
  75. protected override byte[] HashFinal ()
  76. {
  77. byte[] hash = new byte[16];
  78. int i, j;
  79. ProcessFinalBlock(_ProcessingBuffer, 0, _ProcessingBufferCount);
  80. for (i=0; i<4; i++) {
  81. for (j=0; j<4; j++) {
  82. hash[i*4+j] = (byte)(_H[i] >> j*8);
  83. }
  84. }
  85. return hash;
  86. }
  87. /// <summary>
  88. /// Resets the class after use. Called automatically after hashing is done.
  89. /// </summary>
  90. public override void Initialize ()
  91. {
  92. count = 0;
  93. _ProcessingBufferCount = 0;
  94. _H[0] = 0x67452301;
  95. _H[1] = 0xefcdab89;
  96. _H[2] = 0x98badcfe;
  97. _H[3] = 0x10325476;
  98. }
  99. /// <summary>
  100. /// This is the meat of the hash function. It is what processes each block one at a time.
  101. /// </summary>
  102. /// <param name="inputBuffer">Byte array to process data from.</param>
  103. /// <param name="inputOffset">Where in the byte array to start processing.</param>
  104. private void ProcessBlock (byte[] inputBuffer, int inputOffset)
  105. {
  106. uint[] buff = new uint[16];
  107. uint a, b, c, d;
  108. int i;
  109. count += BLOCK_SIZE_BYTES;
  110. for (i=0; i<16; i++) {
  111. buff[i] = (uint)(inputBuffer[inputOffset+4*i])
  112. | (((uint)(inputBuffer[inputOffset+4*i+1])) << 8)
  113. | (((uint)(inputBuffer[inputOffset+4*i+2])) << 16)
  114. | (((uint)(inputBuffer[inputOffset+4*i+3])) << 24);
  115. }
  116. a = _H[0];
  117. b = _H[1];
  118. c = _H[2];
  119. d = _H[3];
  120. // This function was unrolled because it seems to be doubling our performance with current compiler/VM.
  121. // Possibly roll up if this changes.
  122. // ---- Round 1 --------
  123. a += (((c ^ d) & b) ^ d) + (uint) Constants.C0 + buff [0];
  124. a = (a << 7) | (a >> 25);
  125. a += b;
  126. d += (((b ^ c) & a) ^ c) + (uint) Constants.C1 + buff [1];
  127. d = (d << 12) | (d >> 20);
  128. d += a;
  129. c += (((a ^ b) & d) ^ b) + (uint) Constants.C2 + buff [2];
  130. c = (c << 17) | (c >> 15);
  131. c += d;
  132. b += (((d ^ a) & c) ^ a) + (uint) Constants.C3 + buff [3];
  133. b = (b << 22) | (b >> 10);
  134. b += c;
  135. a += (((c ^ d) & b) ^ d) + (uint) Constants.C4 + buff [4];
  136. a = (a << 7) | (a >> 25);
  137. a += b;
  138. d += (((b ^ c) & a) ^ c) + (uint) Constants.C5 + buff [5];
  139. d = (d << 12) | (d >> 20);
  140. d += a;
  141. c += (((a ^ b) & d) ^ b) + (uint) Constants.C6 + buff [6];
  142. c = (c << 17) | (c >> 15);
  143. c += d;
  144. b += (((d ^ a) & c) ^ a) + (uint) Constants.C7 + buff [7];
  145. b = (b << 22) | (b >> 10);
  146. b += c;
  147. a += (((c ^ d) & b) ^ d) + (uint) Constants.C8 + buff [8];
  148. a = (a << 7) | (a >> 25);
  149. a += b;
  150. d += (((b ^ c) & a) ^ c) + (uint) Constants.C9 + buff [9];
  151. d = (d << 12) | (d >> 20);
  152. d += a;
  153. c += (((a ^ b) & d) ^ b) + (uint) Constants.C10 + buff [10];
  154. c = (c << 17) | (c >> 15);
  155. c += d;
  156. b += (((d ^ a) & c) ^ a) + (uint) Constants.C11 + buff [11];
  157. b = (b << 22) | (b >> 10);
  158. b += c;
  159. a += (((c ^ d) & b) ^ d) + (uint) Constants.C12 + buff [12];
  160. a = (a << 7) | (a >> 25);
  161. a += b;
  162. d += (((b ^ c) & a) ^ c) + (uint) Constants.C13 + buff [13];
  163. d = (d << 12) | (d >> 20);
  164. d += a;
  165. c += (((a ^ b) & d) ^ b) + (uint) Constants.C14 + buff [14];
  166. c = (c << 17) | (c >> 15);
  167. c += d;
  168. b += (((d ^ a) & c) ^ a) + (uint) Constants.C15 + buff [15];
  169. b = (b << 22) | (b >> 10);
  170. b += c;
  171. // ---- Round 2 --------
  172. a += (((b ^ c) & d) ^ c) + (uint) Constants.C16 + buff [1];
  173. a = (a << 5) | (a >> 27);
  174. a += b;
  175. d += (((a ^ b) & c) ^ b) + (uint) Constants.C17 + buff [6];
  176. d = (d << 9) | (d >> 23);
  177. d += a;
  178. c += (((d ^ a) & b) ^ a) + (uint) Constants.C18 + buff [11];
  179. c = (c << 14) | (c >> 18);
  180. c += d;
  181. b += (((c ^ d) & a) ^ d) + (uint) Constants.C19 + buff [0];
  182. b = (b << 20) | (b >> 12);
  183. b += c;
  184. a += (((b ^ c) & d) ^ c) + (uint) Constants.C20 + buff [5];
  185. a = (a << 5) | (a >> 27);
  186. a += b;
  187. d += (((a ^ b) & c) ^ b) + (uint) Constants.C21 + buff [10];
  188. d = (d << 9) | (d >> 23);
  189. d += a;
  190. c += (((d ^ a) & b) ^ a) + (uint) Constants.C22 + buff [15];
  191. c = (c << 14) | (c >> 18);
  192. c += d;
  193. b += (((c ^ d) & a) ^ d) + (uint) Constants.C23 + buff [4];
  194. b = (b << 20) | (b >> 12);
  195. b += c;
  196. a += (((b ^ c) & d) ^ c) + (uint) Constants.C24 + buff [9];
  197. a = (a << 5) | (a >> 27);
  198. a += b;
  199. d += (((a ^ b) & c) ^ b) + (uint) Constants.C25 + buff [14];
  200. d = (d << 9) | (d >> 23);
  201. d += a;
  202. c += (((d ^ a) & b) ^ a) + (uint) Constants.C26 + buff [3];
  203. c = (c << 14) | (c >> 18);
  204. c += d;
  205. b += (((c ^ d) & a) ^ d) + (uint) Constants.C27 + buff [8];
  206. b = (b << 20) | (b >> 12);
  207. b += c;
  208. a += (((b ^ c) & d) ^ c) + (uint) Constants.C28 + buff [13];
  209. a = (a << 5) | (a >> 27);
  210. a += b;
  211. d += (((a ^ b) & c) ^ b) + (uint) Constants.C29 + buff [2];
  212. d = (d << 9) | (d >> 23);
  213. d += a;
  214. c += (((d ^ a) & b) ^ a) + (uint) Constants.C30 + buff [7];
  215. c = (c << 14) | (c >> 18);
  216. c += d;
  217. b += (((c ^ d) & a) ^ d) + (uint) Constants.C31 + buff [12];
  218. b = (b << 20) | (b >> 12);
  219. b += c;
  220. // ---- Round 3 --------
  221. a += (b ^ c ^ d) + (uint) Constants.C32 + buff [5];
  222. a = (a << 4) | (a >> 28);
  223. a += b;
  224. d += (a ^ b ^ c) + (uint) Constants.C33 + buff [8];
  225. d = (d << 11) | (d >> 21);
  226. d += a;
  227. c += (d ^ a ^ b) + (uint) Constants.C34 + buff [11];
  228. c = (c << 16) | (c >> 16);
  229. c += d;
  230. b += (c ^ d ^ a) + (uint) Constants.C35 + buff [14];
  231. b = (b << 23) | (b >> 9);
  232. b += c;
  233. a += (b ^ c ^ d) + (uint) Constants.C36 + buff [1];
  234. a = (a << 4) | (a >> 28);
  235. a += b;
  236. d += (a ^ b ^ c) + (uint) Constants.C37 + buff [4];
  237. d = (d << 11) | (d >> 21);
  238. d += a;
  239. c += (d ^ a ^ b) + (uint) Constants.C38 + buff [7];
  240. c = (c << 16) | (c >> 16);
  241. c += d;
  242. b += (c ^ d ^ a) + (uint) Constants.C39 + buff [10];
  243. b = (b << 23) | (b >> 9);
  244. b += c;
  245. a += (b ^ c ^ d) + (uint) Constants.C40 + buff [13];
  246. a = (a << 4) | (a >> 28);
  247. a += b;
  248. d += (a ^ b ^ c) + (uint) Constants.C41 + buff [0];
  249. d = (d << 11) | (d >> 21);
  250. d += a;
  251. c += (d ^ a ^ b) + (uint) Constants.C42 + buff [3];
  252. c = (c << 16) | (c >> 16);
  253. c += d;
  254. b += (c ^ d ^ a) + (uint) Constants.C43 + buff [6];
  255. b = (b << 23) | (b >> 9);
  256. b += c;
  257. a += (b ^ c ^ d) + (uint) Constants.C44 + buff [9];
  258. a = (a << 4) | (a >> 28);
  259. a += b;
  260. d += (a ^ b ^ c) + (uint) Constants.C45 + buff [12];
  261. d = (d << 11) | (d >> 21);
  262. d += a;
  263. c += (d ^ a ^ b) + (uint) Constants.C46 + buff [15];
  264. c = (c << 16) | (c >> 16);
  265. c += d;
  266. b += (c ^ d ^ a) + (uint) Constants.C47 + buff [2];
  267. b = (b << 23) | (b >> 9);
  268. b += c;
  269. // ---- Round 4 --------
  270. a += (((~d) | b) ^ c) + (uint) Constants.C48 + buff [0];
  271. a = (a << 6) | (a >> 26);
  272. a += b;
  273. d += (((~c) | a) ^ b) + (uint) Constants.C49 + buff [7];
  274. d = (d << 10) | (d >> 22);
  275. d += a;
  276. c += (((~b) | d) ^ a) + (uint) Constants.C50 + buff [14];
  277. c = (c << 15) | (c >> 17);
  278. c += d;
  279. b += (((~a) | c) ^ d) + (uint) Constants.C51 + buff [5];
  280. b = (b << 21) | (b >> 11);
  281. b += c;
  282. a += (((~d) | b) ^ c) + (uint) Constants.C52 + buff [12];
  283. a = (a << 6) | (a >> 26);
  284. a += b;
  285. d += (((~c) | a) ^ b) + (uint) Constants.C53 + buff [3];
  286. d = (d << 10) | (d >> 22);
  287. d += a;
  288. c += (((~b) | d) ^ a) + (uint) Constants.C54 + buff [10];
  289. c = (c << 15) | (c >> 17);
  290. c += d;
  291. b += (((~a) | c) ^ d) + (uint) Constants.C55 + buff [1];
  292. b = (b << 21) | (b >> 11);
  293. b += c;
  294. a += (((~d) | b) ^ c) + (uint) Constants.C56 + buff [8];
  295. a = (a << 6) | (a >> 26);
  296. a += b;
  297. d += (((~c) | a) ^ b) + (uint) Constants.C57 + buff [15];
  298. d = (d << 10) | (d >> 22);
  299. d += a;
  300. c += (((~b) | d) ^ a) + (uint) Constants.C58 + buff [6];
  301. c = (c << 15) | (c >> 17);
  302. c += d;
  303. b += (((~a) | c) ^ d) + (uint) Constants.C59 + buff [13];
  304. b = (b << 21) | (b >> 11);
  305. b += c;
  306. a += (((~d) | b) ^ c) + (uint) Constants.C60 + buff [4];
  307. a = (a << 6) | (a >> 26);
  308. a += b;
  309. d += (((~c) | a) ^ b) + (uint) Constants.C61 + buff [11];
  310. d = (d << 10) | (d >> 22);
  311. d += a;
  312. c += (((~b) | d) ^ a) + (uint) Constants.C62 + buff [2];
  313. c = (c << 15) | (c >> 17);
  314. c += d;
  315. b += (((~a) | c) ^ d) + (uint) Constants.C63 + buff [9];
  316. b = (b << 21) | (b >> 11);
  317. b += c;
  318. _H[0] += a;
  319. _H[1] += b;
  320. _H[2] += c;
  321. _H[3] += d;
  322. }
  323. /// <summary>
  324. /// Pads and then processes the final block.
  325. /// </summary>
  326. /// <param name="inputBuffer">Buffer to grab data from.</param>
  327. /// <param name="inputOffset">Position in buffer in bytes to get data from.</param>
  328. /// <param name="inputCount">How much data in bytes in the buffer to use.</param>
  329. private void ProcessFinalBlock (byte[] inputBuffer, int inputOffset, int inputCount)
  330. {
  331. byte[] fooBuffer;
  332. int paddingSize;
  333. int i;
  334. uint size;
  335. paddingSize = (int)(56 - (inputCount + count) % BLOCK_SIZE_BYTES);
  336. if (paddingSize < 1)
  337. paddingSize += BLOCK_SIZE_BYTES;
  338. fooBuffer = new byte[inputCount+paddingSize+8];
  339. for (i=0; i<inputCount; i++) {
  340. fooBuffer[i] = inputBuffer[i+inputOffset];
  341. }
  342. fooBuffer[inputCount] = 0x80;
  343. for (i=inputCount+1; i<inputCount+paddingSize; i++) {
  344. fooBuffer[i] = 0x00;
  345. }
  346. size = (uint)(count+inputCount);
  347. size *= 8;
  348. fooBuffer[inputCount+paddingSize] = (byte)((size) >> 0);
  349. fooBuffer[inputCount+paddingSize+1] = (byte)((size) >> 8);
  350. fooBuffer[inputCount+paddingSize+2] = (byte)((size) >> 16);
  351. fooBuffer[inputCount+paddingSize+3] = (byte)((size) >> 24);
  352. fooBuffer[inputCount+paddingSize+4] = 0x00;
  353. fooBuffer[inputCount+paddingSize+5] = 0x00;
  354. fooBuffer[inputCount+paddingSize+6] = 0x00;
  355. fooBuffer[inputCount+paddingSize+7] = 0x00;
  356. ProcessBlock(fooBuffer, 0);
  357. if (inputCount+paddingSize+8 == 128) {
  358. ProcessBlock(fooBuffer, 64);
  359. }
  360. }
  361. private enum Constants : uint {
  362. C0 = 0xd76aa478, C1 = 0xe8c7b756, C2 = 0x242070db,
  363. C3 = 0xc1bdceee, C4 = 0xf57c0faf, C5 = 0x4787c62a,
  364. C6 = 0xa8304613, C7 = 0xfd469501, C8 = 0x698098d8,
  365. C9 = 0x8b44f7af,C10 = 0xffff5bb1,C11 = 0x895cd7be,
  366. C12 = 0x6b901122,C13 = 0xfd987193,C14 = 0xa679438e,
  367. C15 = 0x49b40821,C16 = 0xf61e2562,C17 = 0xc040b340,
  368. C18 = 0x265e5a51,C19 = 0xe9b6c7aa,C20 = 0xd62f105d,
  369. C21 = 0x02441453,C22 = 0xd8a1e681,C23 = 0xe7d3fbc8,
  370. C24 = 0x21e1cde6,C25 = 0xc33707d6,C26 = 0xf4d50d87,
  371. C27 = 0x455a14ed,C28 = 0xa9e3e905,C29 = 0xfcefa3f8,
  372. C30 = 0x676f02d9,C31 = 0x8d2a4c8a,C32 = 0xfffa3942,
  373. C33 = 0x8771f681,C34 = 0x6d9d6122,C35 = 0xfde5380c,
  374. C36 = 0xa4beea44,C37 = 0x4bdecfa9,C38 = 0xf6bb4b60,
  375. C39 = 0xbebfbc70,C40 = 0x289b7ec6,C41 = 0xeaa127fa,
  376. C42 = 0xd4ef3085,C43 = 0x04881d05,C44 = 0xd9d4d039,
  377. C45 = 0xe6db99e5,C46 = 0x1fa27cf8,C47 = 0xc4ac5665,
  378. C48 = 0xf4292244,C49 = 0x432aff97,C50 = 0xab9423a7,
  379. C51 = 0xfc93a039,C52 = 0x655b59c3,C53 = 0x8f0ccc92,
  380. C54 = 0xffeff47d,C55 = 0x85845dd1,C56 = 0x6fa87e4f,
  381. C57 = 0xfe2ce6e0,C58 = 0xa3014314,C59 = 0x4e0811a1,
  382. C60 = 0xf7537e82,C61 = 0xbd3af235,C62 = 0x2ad7d2bb,
  383. C63 = 0xeb86d391
  384. }
  385. }
  386. }