You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

268 lines
9.5 KiB

  1. #if NET20
  2. using System;
  3. using System.Security;
  4. using System.Security.Cryptography;
  5. namespace Apewer.Internals
  6. {
  7. internal class SHA256CryptoServiceProvider : HashAlgorithm
  8. {
  9. private byte[] _buffer;
  10. private long _count;
  11. private uint[] _stateSHA256;
  12. private uint[] _W;
  13. private static readonly uint[] _K = new uint[64]
  14. {
  15. 1116352408u, 1899447441u, 3049323471u, 3921009573u, 961987163u, 1508970993u, 2453635748u, 2870763221u,
  16. 3624381080u, 310598401u, 607225278u, 1426881987u, 1925078388u, 2162078206u, 2614888103u, 3248222580u,
  17. 3835390401u, 4022224774u, 264347078u, 604807628u, 770255983u, 1249150122u, 1555081692u, 1996064986u,
  18. 2554220882u, 2821834349u, 2952996808u, 3210313671u, 3336571891u, 3584528711u, 113926993u, 338241895u,
  19. 666307205u, 773529912u, 1294757372u, 1396182291u, 1695183700u, 1986661051u, 2177026350u, 2456956037u,
  20. 2730485921u, 2820302411u, 3259730800u, 3345764771u, 3516065817u, 3600352804u, 4094571909u, 275423344u,
  21. 430227734u, 506948616u, 659060556u, 883997877u, 958139571u, 1322822218u, 1537002063u, 1747873779u,
  22. 1955562222u, 2024104815u, 2227730452u, 2361852424u, 2428436474u, 2756734187u, 3204031479u, 3329325298u
  23. };
  24. public SHA256CryptoServiceProvider()
  25. {
  26. HashSizeValue = 256;
  27. _stateSHA256 = new uint[8];
  28. _buffer = new byte[64];
  29. _W = new uint[64];
  30. InitializeState();
  31. }
  32. public override void Initialize()
  33. {
  34. InitializeState();
  35. Array.Clear(_buffer, 0, _buffer.Length);
  36. Array.Clear(_W, 0, _W.Length);
  37. }
  38. protected override void HashCore(byte[] rgb, int ibStart, int cbSize)
  39. {
  40. _HashData(rgb, ibStart, cbSize);
  41. }
  42. protected override byte[] HashFinal()
  43. {
  44. return _EndHash();
  45. }
  46. private void InitializeState()
  47. {
  48. _count = 0L;
  49. _stateSHA256[0] = 1779033703u;
  50. _stateSHA256[1] = 3144134277u;
  51. _stateSHA256[2] = 1013904242u;
  52. _stateSHA256[3] = 2773480762u;
  53. _stateSHA256[4] = 1359893119u;
  54. _stateSHA256[5] = 2600822924u;
  55. _stateSHA256[6] = 528734635u;
  56. _stateSHA256[7] = 1541459225u;
  57. }
  58. [SecuritySafeCritical]
  59. private unsafe void _HashData(byte[] partIn, int ibStart, int cbSize)
  60. {
  61. int num = cbSize;
  62. int num2 = ibStart;
  63. int num3 = (int)(_count & 0x3F);
  64. _count += num;
  65. fixed (uint* state = _stateSHA256)
  66. {
  67. fixed (byte* block = _buffer)
  68. {
  69. fixed (uint* expandedBuffer = _W)
  70. {
  71. if (num3 > 0 && num3 + num >= 64)
  72. {
  73. Array.Copy(partIn, num2, _buffer, num3, 64 - num3);
  74. num2 += 64 - num3;
  75. num -= 64 - num3;
  76. SHATransform(expandedBuffer, state, block);
  77. num3 = 0;
  78. }
  79. while (num >= 64)
  80. {
  81. Array.Copy(partIn, num2, _buffer, 0, 64);
  82. num2 += 64;
  83. num -= 64;
  84. SHATransform(expandedBuffer, state, block);
  85. }
  86. if (num > 0)
  87. {
  88. Array.Copy(partIn, num2, _buffer, num3, num);
  89. }
  90. }
  91. }
  92. }
  93. }
  94. private byte[] _EndHash()
  95. {
  96. byte[] array = new byte[32];
  97. int num = 64 - (int)(_count & 0x3F);
  98. if (num <= 8)
  99. {
  100. num += 64;
  101. }
  102. byte[] array2 = new byte[num];
  103. array2[0] = 128;
  104. long num2 = _count * 8;
  105. array2[num - 8] = (byte)((num2 >> 56) & 0xFF);
  106. array2[num - 7] = (byte)((num2 >> 48) & 0xFF);
  107. array2[num - 6] = (byte)((num2 >> 40) & 0xFF);
  108. array2[num - 5] = (byte)((num2 >> 32) & 0xFF);
  109. array2[num - 4] = (byte)((num2 >> 24) & 0xFF);
  110. array2[num - 3] = (byte)((num2 >> 16) & 0xFF);
  111. array2[num - 2] = (byte)((num2 >> 8) & 0xFF);
  112. array2[num - 1] = (byte)(num2 & 0xFF);
  113. _HashData(array2, 0, array2.Length);
  114. DWORDToBigEndian(array, _stateSHA256, 8);
  115. HashValue = array;
  116. return array;
  117. }
  118. [SecurityCritical]
  119. private unsafe static void SHATransform(uint* expandedBuffer, uint* state, byte* block)
  120. {
  121. uint num = *state;
  122. uint num2 = state[1];
  123. uint num3 = state[2];
  124. uint num4 = state[3];
  125. uint num5 = state[4];
  126. uint num6 = state[5];
  127. uint num7 = state[6];
  128. uint num8 = state[7];
  129. DWORDFromBigEndian(expandedBuffer, 16, block);
  130. SHA256Expand(expandedBuffer);
  131. int num9;
  132. for (num9 = 0; num9 < 64; num9++)
  133. {
  134. uint num10 = num8 + Sigma_1(num5) + Ch(num5, num6, num7) + _K[num9] + expandedBuffer[num9];
  135. uint num11 = num4 + num10;
  136. uint num12 = num10 + Sigma_0(num) + Maj(num, num2, num3);
  137. num9++;
  138. num10 = num7 + Sigma_1(num11) + Ch(num11, num5, num6) + _K[num9] + expandedBuffer[num9];
  139. uint num13 = num3 + num10;
  140. uint num14 = num10 + Sigma_0(num12) + Maj(num12, num, num2);
  141. num9++;
  142. num10 = num6 + Sigma_1(num13) + Ch(num13, num11, num5) + _K[num9] + expandedBuffer[num9];
  143. uint num15 = num2 + num10;
  144. uint num16 = num10 + Sigma_0(num14) + Maj(num14, num12, num);
  145. num9++;
  146. num10 = num5 + Sigma_1(num15) + Ch(num15, num13, num11) + _K[num9] + expandedBuffer[num9];
  147. uint num17 = num + num10;
  148. uint num18 = num10 + Sigma_0(num16) + Maj(num16, num14, num12);
  149. num9++;
  150. num10 = num11 + Sigma_1(num17) + Ch(num17, num15, num13) + _K[num9] + expandedBuffer[num9];
  151. num8 = num12 + num10;
  152. num4 = num10 + Sigma_0(num18) + Maj(num18, num16, num14);
  153. num9++;
  154. num10 = num13 + Sigma_1(num8) + Ch(num8, num17, num15) + _K[num9] + expandedBuffer[num9];
  155. num7 = num14 + num10;
  156. num3 = num10 + Sigma_0(num4) + Maj(num4, num18, num16);
  157. num9++;
  158. num10 = num15 + Sigma_1(num7) + Ch(num7, num8, num17) + _K[num9] + expandedBuffer[num9];
  159. num6 = num16 + num10;
  160. num2 = num10 + Sigma_0(num3) + Maj(num3, num4, num18);
  161. num9++;
  162. num10 = num17 + Sigma_1(num6) + Ch(num6, num7, num8) + _K[num9] + expandedBuffer[num9];
  163. num5 = num18 + num10;
  164. num = num10 + Sigma_0(num2) + Maj(num2, num3, num4);
  165. }
  166. *state += num;
  167. state[1] += num2;
  168. state[2] += num3;
  169. state[3] += num4;
  170. state[4] += num5;
  171. state[5] += num6;
  172. state[6] += num7;
  173. state[7] += num8;
  174. }
  175. private static uint RotateRight(uint x, int n)
  176. {
  177. return (x >> n) | (x << 32 - n);
  178. }
  179. private static uint Ch(uint x, uint y, uint z)
  180. {
  181. return (x & y) ^ (uint)(((int)x ^ -1) & (int)z);
  182. }
  183. private static uint Maj(uint x, uint y, uint z)
  184. {
  185. return (x & y) ^ (x & z) ^ (y & z);
  186. }
  187. private static uint sigma_0(uint x)
  188. {
  189. return RotateRight(x, 7) ^ RotateRight(x, 18) ^ (x >> 3);
  190. }
  191. private static uint sigma_1(uint x)
  192. {
  193. return RotateRight(x, 17) ^ RotateRight(x, 19) ^ (x >> 10);
  194. }
  195. private static uint Sigma_0(uint x)
  196. {
  197. return RotateRight(x, 2) ^ RotateRight(x, 13) ^ RotateRight(x, 22);
  198. }
  199. private static uint Sigma_1(uint x)
  200. {
  201. return RotateRight(x, 6) ^ RotateRight(x, 11) ^ RotateRight(x, 25);
  202. }
  203. [SecurityCritical]
  204. private unsafe static void SHA256Expand(uint* x)
  205. {
  206. for (int i = 16; i < 64; i++)
  207. {
  208. x[i] = sigma_1(x[i - 2]) + x[i - 7] + sigma_0(x[i - 15]) + x[i - 16];
  209. }
  210. }
  211. private static void DWORDToBigEndian(byte[] block, uint[] x, int digits)
  212. {
  213. int num = 0;
  214. int num2 = 0;
  215. while (num < digits)
  216. {
  217. block[num2] = (byte)((x[num] >> 24) & 0xFF);
  218. block[num2 + 1] = (byte)((x[num] >> 16) & 0xFF);
  219. block[num2 + 2] = (byte)((x[num] >> 8) & 0xFF);
  220. block[num2 + 3] = (byte)(x[num] & 0xFF);
  221. num++;
  222. num2 += 4;
  223. }
  224. }
  225. [SecurityCritical]
  226. private unsafe static void DWORDFromBigEndian(uint* x, int digits, byte* block)
  227. {
  228. int num = 0;
  229. int num2 = 0;
  230. while (num < digits)
  231. {
  232. x[num] = (uint)((block[num2] << 24) | (block[num2 + 1] << 16) | (block[num2 + 2] << 8) | block[num2 + 3]);
  233. num++;
  234. num2 += 4;
  235. }
  236. }
  237. }
  238. }
  239. #endif