MD5CryptoServiceProvider.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510
  1. #if UNITY_WP8
  2. //
  3. // System.Security.Cryptography.MD5CryptoServiceProvider.cs
  4. //
  5. // Authors:
  6. // Matthew S. Ford (Matthew.S.Ford@Rose-Hulman.Edu)
  7. // Sebastien Pouliot (sebastien@ximian.com)
  8. //
  9. // Copyright 2001 by Matthew S. Ford.
  10. // Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
  11. //
  12. // Permission is hereby granted, free of charge, to any person obtaining
  13. // a copy of this software and associated documentation files (the
  14. // "Software"), to deal in the Software without restriction, including
  15. // without limitation the rights to use, copy, modify, merge, publish,
  16. // distribute, sublicense, and/or sell copies of the Software, and to
  17. // permit persons to whom the Software is furnished to do so, subject to
  18. // the following conditions:
  19. //
  20. // The above copyright notice and this permission notice shall be
  21. // included in all copies or substantial portions of the Software.
  22. //
  23. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  24. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  25. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  26. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  27. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  28. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  29. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  30. //
  31. using System;
  32. using System.Runtime.InteropServices;
  33. namespace BestHTTP.PlatformSupport.Cryptography
  34. {
  35. using System.Runtime.InteropServices;
  36. using System.Security.Cryptography;
  37. [ComVisible(true)]
  38. public abstract class MD5 : HashAlgorithm
  39. {
  40. // Why is it protected when others abstract hash classes are public ?
  41. protected MD5()
  42. {
  43. HashSizeValue = 128;
  44. }
  45. public static new MD5 Create()
  46. {
  47. return new BestHTTP.PlatformSupport.Cryptography.MD5CryptoServiceProvider();
  48. }
  49. }
  50. [ComVisible (true)]
  51. public sealed class MD5CryptoServiceProvider : MD5 {
  52. private const int BLOCK_SIZE_BYTES = 64;
  53. private uint[] _H;
  54. private uint[] buff;
  55. private ulong count;
  56. private byte[] _ProcessingBuffer; // Used to start data when passed less than a block worth.
  57. private int _ProcessingBufferCount; // Counts how much data we have stored that still needs processed.
  58. public MD5CryptoServiceProvider ()
  59. {
  60. _H = new uint[4];
  61. buff = new uint[16];
  62. _ProcessingBuffer = new byte [BLOCK_SIZE_BYTES];
  63. Initialize();
  64. }
  65. ~MD5CryptoServiceProvider ()
  66. {
  67. Dispose (false);
  68. }
  69. protected override void Dispose (bool disposing)
  70. {
  71. if (_ProcessingBuffer != null) {
  72. Array.Clear (_ProcessingBuffer, 0, _ProcessingBuffer.Length);
  73. _ProcessingBuffer = null;
  74. }
  75. if (_H != null) {
  76. Array.Clear (_H, 0, _H.Length);
  77. _H = null;
  78. }
  79. if (buff != null) {
  80. Array.Clear (buff, 0, buff.Length);
  81. buff = null;
  82. }
  83. }
  84. protected override void HashCore (byte[] rgb, int ibStart, int cbSize)
  85. {
  86. int i;
  87. State = 1;
  88. if (_ProcessingBufferCount != 0) {
  89. if (cbSize < (BLOCK_SIZE_BYTES - _ProcessingBufferCount)) {
  90. System.Buffer.BlockCopy (rgb, ibStart, _ProcessingBuffer, _ProcessingBufferCount, cbSize);
  91. _ProcessingBufferCount += cbSize;
  92. return;
  93. }
  94. else {
  95. i = (BLOCK_SIZE_BYTES - _ProcessingBufferCount);
  96. System.Buffer.BlockCopy (rgb, ibStart, _ProcessingBuffer, _ProcessingBufferCount, i);
  97. ProcessBlock (_ProcessingBuffer, 0);
  98. _ProcessingBufferCount = 0;
  99. ibStart += i;
  100. cbSize -= i;
  101. }
  102. }
  103. for (i = 0; i < cbSize - cbSize % BLOCK_SIZE_BYTES; i += BLOCK_SIZE_BYTES) {
  104. ProcessBlock (rgb, ibStart + i);
  105. }
  106. if (cbSize % BLOCK_SIZE_BYTES != 0) {
  107. System.Buffer.BlockCopy (rgb, cbSize - cbSize % BLOCK_SIZE_BYTES + ibStart, _ProcessingBuffer, 0, cbSize % BLOCK_SIZE_BYTES);
  108. _ProcessingBufferCount = cbSize % BLOCK_SIZE_BYTES;
  109. }
  110. }
  111. protected override byte[] HashFinal ()
  112. {
  113. byte[] hash = new byte[16];
  114. int i, j;
  115. ProcessFinalBlock (_ProcessingBuffer, 0, _ProcessingBufferCount);
  116. for (i=0; i<4; i++) {
  117. for (j=0; j<4; j++) {
  118. hash[i*4+j] = (byte)(_H[i] >> j*8);
  119. }
  120. }
  121. return hash;
  122. }
  123. public override void Initialize ()
  124. {
  125. count = 0;
  126. _ProcessingBufferCount = 0;
  127. _H[0] = 0x67452301;
  128. _H[1] = 0xefcdab89;
  129. _H[2] = 0x98badcfe;
  130. _H[3] = 0x10325476;
  131. }
  132. private void ProcessBlock (byte[] inputBuffer, int inputOffset)
  133. {
  134. uint a, b, c, d;
  135. int i;
  136. count += BLOCK_SIZE_BYTES;
  137. for (i=0; i<16; i++) {
  138. buff[i] = (uint)(inputBuffer[inputOffset+4*i])
  139. | (((uint)(inputBuffer[inputOffset+4*i+1])) << 8)
  140. | (((uint)(inputBuffer[inputOffset+4*i+2])) << 16)
  141. | (((uint)(inputBuffer[inputOffset+4*i+3])) << 24);
  142. }
  143. a = _H[0];
  144. b = _H[1];
  145. c = _H[2];
  146. d = _H[3];
  147. // This function was unrolled because it seems to be doubling our performance with current compiler/VM.
  148. // Possibly roll up if this changes.
  149. // ---- Round 1 --------
  150. a += (((c ^ d) & b) ^ d) + (uint) K [0] + buff [0];
  151. a = (a << 7) | (a >> 25);
  152. a += b;
  153. d += (((b ^ c) & a) ^ c) + (uint) K [1] + buff [1];
  154. d = (d << 12) | (d >> 20);
  155. d += a;
  156. c += (((a ^ b) & d) ^ b) + (uint) K [2] + buff [2];
  157. c = (c << 17) | (c >> 15);
  158. c += d;
  159. b += (((d ^ a) & c) ^ a) + (uint) K [3] + buff [3];
  160. b = (b << 22) | (b >> 10);
  161. b += c;
  162. a += (((c ^ d) & b) ^ d) + (uint) K [4] + buff [4];
  163. a = (a << 7) | (a >> 25);
  164. a += b;
  165. d += (((b ^ c) & a) ^ c) + (uint) K [5] + buff [5];
  166. d = (d << 12) | (d >> 20);
  167. d += a;
  168. c += (((a ^ b) & d) ^ b) + (uint) K [6] + buff [6];
  169. c = (c << 17) | (c >> 15);
  170. c += d;
  171. b += (((d ^ a) & c) ^ a) + (uint) K [7] + buff [7];
  172. b = (b << 22) | (b >> 10);
  173. b += c;
  174. a += (((c ^ d) & b) ^ d) + (uint) K [8] + buff [8];
  175. a = (a << 7) | (a >> 25);
  176. a += b;
  177. d += (((b ^ c) & a) ^ c) + (uint) K [9] + buff [9];
  178. d = (d << 12) | (d >> 20);
  179. d += a;
  180. c += (((a ^ b) & d) ^ b) + (uint) K [10] + buff [10];
  181. c = (c << 17) | (c >> 15);
  182. c += d;
  183. b += (((d ^ a) & c) ^ a) + (uint) K [11] + buff [11];
  184. b = (b << 22) | (b >> 10);
  185. b += c;
  186. a += (((c ^ d) & b) ^ d) + (uint) K [12] + buff [12];
  187. a = (a << 7) | (a >> 25);
  188. a += b;
  189. d += (((b ^ c) & a) ^ c) + (uint) K [13] + buff [13];
  190. d = (d << 12) | (d >> 20);
  191. d += a;
  192. c += (((a ^ b) & d) ^ b) + (uint) K [14] + buff [14];
  193. c = (c << 17) | (c >> 15);
  194. c += d;
  195. b += (((d ^ a) & c) ^ a) + (uint) K [15] + buff [15];
  196. b = (b << 22) | (b >> 10);
  197. b += c;
  198. // ---- Round 2 --------
  199. a += (((b ^ c) & d) ^ c) + (uint) K [16] + buff [1];
  200. a = (a << 5) | (a >> 27);
  201. a += b;
  202. d += (((a ^ b) & c) ^ b) + (uint) K [17] + buff [6];
  203. d = (d << 9) | (d >> 23);
  204. d += a;
  205. c += (((d ^ a) & b) ^ a) + (uint) K [18] + buff [11];
  206. c = (c << 14) | (c >> 18);
  207. c += d;
  208. b += (((c ^ d) & a) ^ d) + (uint) K [19] + buff [0];
  209. b = (b << 20) | (b >> 12);
  210. b += c;
  211. a += (((b ^ c) & d) ^ c) + (uint) K [20] + buff [5];
  212. a = (a << 5) | (a >> 27);
  213. a += b;
  214. d += (((a ^ b) & c) ^ b) + (uint) K [21] + buff [10];
  215. d = (d << 9) | (d >> 23);
  216. d += a;
  217. c += (((d ^ a) & b) ^ a) + (uint) K [22] + buff [15];
  218. c = (c << 14) | (c >> 18);
  219. c += d;
  220. b += (((c ^ d) & a) ^ d) + (uint) K [23] + buff [4];
  221. b = (b << 20) | (b >> 12);
  222. b += c;
  223. a += (((b ^ c) & d) ^ c) + (uint) K [24] + buff [9];
  224. a = (a << 5) | (a >> 27);
  225. a += b;
  226. d += (((a ^ b) & c) ^ b) + (uint) K [25] + buff [14];
  227. d = (d << 9) | (d >> 23);
  228. d += a;
  229. c += (((d ^ a) & b) ^ a) + (uint) K [26] + buff [3];
  230. c = (c << 14) | (c >> 18);
  231. c += d;
  232. b += (((c ^ d) & a) ^ d) + (uint) K [27] + buff [8];
  233. b = (b << 20) | (b >> 12);
  234. b += c;
  235. a += (((b ^ c) & d) ^ c) + (uint) K [28] + buff [13];
  236. a = (a << 5) | (a >> 27);
  237. a += b;
  238. d += (((a ^ b) & c) ^ b) + (uint) K [29] + buff [2];
  239. d = (d << 9) | (d >> 23);
  240. d += a;
  241. c += (((d ^ a) & b) ^ a) + (uint) K [30] + buff [7];
  242. c = (c << 14) | (c >> 18);
  243. c += d;
  244. b += (((c ^ d) & a) ^ d) + (uint) K [31] + buff [12];
  245. b = (b << 20) | (b >> 12);
  246. b += c;
  247. // ---- Round 3 --------
  248. a += (b ^ c ^ d) + (uint) K [32] + buff [5];
  249. a = (a << 4) | (a >> 28);
  250. a += b;
  251. d += (a ^ b ^ c) + (uint) K [33] + buff [8];
  252. d = (d << 11) | (d >> 21);
  253. d += a;
  254. c += (d ^ a ^ b) + (uint) K [34] + buff [11];
  255. c = (c << 16) | (c >> 16);
  256. c += d;
  257. b += (c ^ d ^ a) + (uint) K [35] + buff [14];
  258. b = (b << 23) | (b >> 9);
  259. b += c;
  260. a += (b ^ c ^ d) + (uint) K [36] + buff [1];
  261. a = (a << 4) | (a >> 28);
  262. a += b;
  263. d += (a ^ b ^ c) + (uint) K [37] + buff [4];
  264. d = (d << 11) | (d >> 21);
  265. d += a;
  266. c += (d ^ a ^ b) + (uint) K [38] + buff [7];
  267. c = (c << 16) | (c >> 16);
  268. c += d;
  269. b += (c ^ d ^ a) + (uint) K [39] + buff [10];
  270. b = (b << 23) | (b >> 9);
  271. b += c;
  272. a += (b ^ c ^ d) + (uint) K [40] + buff [13];
  273. a = (a << 4) | (a >> 28);
  274. a += b;
  275. d += (a ^ b ^ c) + (uint) K [41] + buff [0];
  276. d = (d << 11) | (d >> 21);
  277. d += a;
  278. c += (d ^ a ^ b) + (uint) K [42] + buff [3];
  279. c = (c << 16) | (c >> 16);
  280. c += d;
  281. b += (c ^ d ^ a) + (uint) K [43] + buff [6];
  282. b = (b << 23) | (b >> 9);
  283. b += c;
  284. a += (b ^ c ^ d) + (uint) K [44] + buff [9];
  285. a = (a << 4) | (a >> 28);
  286. a += b;
  287. d += (a ^ b ^ c) + (uint) K [45] + buff [12];
  288. d = (d << 11) | (d >> 21);
  289. d += a;
  290. c += (d ^ a ^ b) + (uint) K [46] + buff [15];
  291. c = (c << 16) | (c >> 16);
  292. c += d;
  293. b += (c ^ d ^ a) + (uint) K [47] + buff [2];
  294. b = (b << 23) | (b >> 9);
  295. b += c;
  296. // ---- Round 4 --------
  297. a += (((~d) | b) ^ c) + (uint) K [48] + buff [0];
  298. a = (a << 6) | (a >> 26);
  299. a += b;
  300. d += (((~c) | a) ^ b) + (uint) K [49] + buff [7];
  301. d = (d << 10) | (d >> 22);
  302. d += a;
  303. c += (((~b) | d) ^ a) + (uint) K [50] + buff [14];
  304. c = (c << 15) | (c >> 17);
  305. c += d;
  306. b += (((~a) | c) ^ d) + (uint) K [51] + buff [5];
  307. b = (b << 21) | (b >> 11);
  308. b += c;
  309. a += (((~d) | b) ^ c) + (uint) K [52] + buff [12];
  310. a = (a << 6) | (a >> 26);
  311. a += b;
  312. d += (((~c) | a) ^ b) + (uint) K [53] + buff [3];
  313. d = (d << 10) | (d >> 22);
  314. d += a;
  315. c += (((~b) | d) ^ a) + (uint) K [54] + buff [10];
  316. c = (c << 15) | (c >> 17);
  317. c += d;
  318. b += (((~a) | c) ^ d) + (uint) K [55] + buff [1];
  319. b = (b << 21) | (b >> 11);
  320. b += c;
  321. a += (((~d) | b) ^ c) + (uint) K [56] + buff [8];
  322. a = (a << 6) | (a >> 26);
  323. a += b;
  324. d += (((~c) | a) ^ b) + (uint) K [57] + buff [15];
  325. d = (d << 10) | (d >> 22);
  326. d += a;
  327. c += (((~b) | d) ^ a) + (uint) K [58] + buff [6];
  328. c = (c << 15) | (c >> 17);
  329. c += d;
  330. b += (((~a) | c) ^ d) + (uint) K [59] + buff [13];
  331. b = (b << 21) | (b >> 11);
  332. b += c;
  333. a += (((~d) | b) ^ c) + (uint) K [60] + buff [4];
  334. a = (a << 6) | (a >> 26);
  335. a += b;
  336. d += (((~c) | a) ^ b) + (uint) K [61] + buff [11];
  337. d = (d << 10) | (d >> 22);
  338. d += a;
  339. c += (((~b) | d) ^ a) + (uint) K [62] + buff [2];
  340. c = (c << 15) | (c >> 17);
  341. c += d;
  342. b += (((~a) | c) ^ d) + (uint) K [63] + buff [9];
  343. b = (b << 21) | (b >> 11);
  344. b += c;
  345. _H [0] += a;
  346. _H [1] += b;
  347. _H [2] += c;
  348. _H [3] += d;
  349. }
  350. private void ProcessFinalBlock (byte[] inputBuffer, int inputOffset, int inputCount)
  351. {
  352. ulong total = count + (ulong)inputCount;
  353. int paddingSize = (int)(56 - total % BLOCK_SIZE_BYTES);
  354. if (paddingSize < 1)
  355. paddingSize += BLOCK_SIZE_BYTES;
  356. byte[] fooBuffer = new byte [inputCount+paddingSize+8];
  357. for (int i=0; i<inputCount; i++) {
  358. fooBuffer[i] = inputBuffer[i+inputOffset];
  359. }
  360. fooBuffer[inputCount] = 0x80;
  361. for (int i=inputCount+1; i<inputCount+paddingSize; i++) {
  362. fooBuffer[i] = 0x00;
  363. }
  364. // I deal in bytes. The algorithm deals in bits.
  365. ulong size = total << 3;
  366. AddLength (size, fooBuffer, inputCount+paddingSize);
  367. ProcessBlock (fooBuffer, 0);
  368. if (inputCount+paddingSize+8 == 128) {
  369. ProcessBlock(fooBuffer, 64);
  370. }
  371. }
  372. internal void AddLength (ulong length, byte[] buffer, int position)
  373. {
  374. buffer [position++] = (byte)(length);
  375. buffer [position++] = (byte)(length >> 8);
  376. buffer [position++] = (byte)(length >> 16);
  377. buffer [position++] = (byte)(length >> 24);
  378. buffer [position++] = (byte)(length >> 32);
  379. buffer [position++] = (byte)(length >> 40);
  380. buffer [position++] = (byte)(length >> 48);
  381. buffer [position] = (byte)(length >> 56);
  382. }
  383. private readonly static uint[] K = {
  384. 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
  385. 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
  386. 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
  387. 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
  388. 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
  389. 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
  390. 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
  391. 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
  392. 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
  393. 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
  394. 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,
  395. 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
  396. 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
  397. 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
  398. 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
  399. 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391
  400. };
  401. }
  402. }
  403. #endif