Haraka512Digest.cs 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
  2. #pragma warning disable
  3. using System;
  4. namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Digests
  5. {
  6. public sealed class Haraka512Digest
  7. : HarakaBase
  8. {
  9. private readonly byte[] m_buf;
  10. private int m_bufPos;
  11. public Haraka512Digest()
  12. {
  13. m_buf = new byte[64];
  14. m_bufPos = 0;
  15. }
  16. public override string AlgorithmName => "Haraka-512";
  17. public override int GetByteLength() => 64;
  18. public override void Update(byte input)
  19. {
  20. if (m_bufPos > 64 - 1)
  21. throw new ArgumentException("total input cannot be more than 64 bytes");
  22. m_buf[m_bufPos++] = input;
  23. }
  24. public override void BlockUpdate(byte[] input, int inOff, int len)
  25. {
  26. if (m_bufPos > 64 - len)
  27. throw new ArgumentException("total input cannot be more than 64 bytes");
  28. Array.Copy(input, inOff, m_buf, m_bufPos, len);
  29. m_bufPos += len;
  30. }
  31. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  32. public override void BlockUpdate(ReadOnlySpan<byte> input)
  33. {
  34. if (m_bufPos > 64 - input.Length)
  35. throw new ArgumentException("total input cannot be more than 64 bytes");
  36. input.CopyTo(m_buf.AsSpan(m_bufPos));
  37. m_bufPos += input.Length;
  38. }
  39. #endif
  40. public override int DoFinal(byte[] output, int outOff)
  41. {
  42. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  43. return DoFinal(output.AsSpan(outOff));
  44. #else
  45. if (m_bufPos != 64)
  46. throw new ArgumentException("input must be exactly 64 bytes");
  47. if (output.Length - outOff < 32)
  48. throw new ArgumentException("output too short to receive digest");
  49. int rv = Haraka512256(m_buf, output, outOff);
  50. Reset();
  51. return rv;
  52. #endif
  53. }
  54. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  55. public override int DoFinal(Span<byte> output)
  56. {
  57. if (m_bufPos != 64)
  58. throw new ArgumentException("input must be exactly 64 bytes");
  59. if (output.Length < 32)
  60. throw new ArgumentException("output too short to receive digest");
  61. #if NETCOREAPP3_0_OR_GREATER
  62. if (Haraka512_X86.IsSupported)
  63. {
  64. Haraka512_X86.Hash(m_buf, output);
  65. Reset();
  66. return 32;
  67. }
  68. #endif
  69. int rv = Haraka512256(m_buf, output);
  70. Reset();
  71. return rv;
  72. }
  73. #endif
  74. public override void Reset()
  75. {
  76. m_bufPos = 0;
  77. Array.Clear(m_buf, 0, 64);
  78. }
  79. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  80. private static int Haraka512256(ReadOnlySpan<byte> msg, Span<byte> output)
  81. {
  82. byte[][] s1 = new byte[4][];
  83. s1[0] = new byte[16];
  84. s1[1] = new byte[16];
  85. s1[2] = new byte[16];
  86. s1[3] = new byte[16];
  87. byte[][] s2 = new byte[4][];
  88. s2[0] = new byte[16];
  89. s2[1] = new byte[16];
  90. s2[2] = new byte[16];
  91. s2[3] = new byte[16];
  92. msg[ ..16].CopyTo(s1[0]);
  93. msg[16..32].CopyTo(s1[1]);
  94. msg[32..48].CopyTo(s1[2]);
  95. msg[48..64].CopyTo(s1[3]);
  96. s1[0] = AesEnc(s1[0], RC[0]);
  97. s1[1] = AesEnc(s1[1], RC[1]);
  98. s1[2] = AesEnc(s1[2], RC[2]);
  99. s1[3] = AesEnc(s1[3], RC[3]);
  100. s1[0] = AesEnc(s1[0], RC[4]);
  101. s1[1] = AesEnc(s1[1], RC[5]);
  102. s1[2] = AesEnc(s1[2], RC[6]);
  103. s1[3] = AesEnc(s1[3], RC[7]);
  104. Mix512(s1, s2);
  105. s1[0] = AesEnc(s2[0], RC[8]);
  106. s1[1] = AesEnc(s2[1], RC[9]);
  107. s1[2] = AesEnc(s2[2], RC[10]);
  108. s1[3] = AesEnc(s2[3], RC[11]);
  109. s1[0] = AesEnc(s1[0], RC[12]);
  110. s1[1] = AesEnc(s1[1], RC[13]);
  111. s1[2] = AesEnc(s1[2], RC[14]);
  112. s1[3] = AesEnc(s1[3], RC[15]);
  113. Mix512(s1, s2);
  114. s1[0] = AesEnc(s2[0], RC[16]);
  115. s1[1] = AesEnc(s2[1], RC[17]);
  116. s1[2] = AesEnc(s2[2], RC[18]);
  117. s1[3] = AesEnc(s2[3], RC[19]);
  118. s1[0] = AesEnc(s1[0], RC[20]);
  119. s1[1] = AesEnc(s1[1], RC[21]);
  120. s1[2] = AesEnc(s1[2], RC[22]);
  121. s1[3] = AesEnc(s1[3], RC[23]);
  122. Mix512(s1, s2);
  123. s1[0] = AesEnc(s2[0], RC[24]);
  124. s1[1] = AesEnc(s2[1], RC[25]);
  125. s1[2] = AesEnc(s2[2], RC[26]);
  126. s1[3] = AesEnc(s2[3], RC[27]);
  127. s1[0] = AesEnc(s1[0], RC[28]);
  128. s1[1] = AesEnc(s1[1], RC[29]);
  129. s1[2] = AesEnc(s1[2], RC[30]);
  130. s1[3] = AesEnc(s1[3], RC[31]);
  131. Mix512(s1, s2);
  132. s1[0] = AesEnc(s2[0], RC[32]);
  133. s1[1] = AesEnc(s2[1], RC[33]);
  134. s1[2] = AesEnc(s2[2], RC[34]);
  135. s1[3] = AesEnc(s2[3], RC[35]);
  136. s1[0] = AesEnc(s1[0], RC[36]);
  137. s1[1] = AesEnc(s1[1], RC[37]);
  138. s1[2] = AesEnc(s1[2], RC[38]);
  139. s1[3] = AesEnc(s1[3], RC[39]);
  140. Mix512(s1, s2);
  141. Xor(s2[0], msg, s1[0]);
  142. Xor(s2[1], msg[16..], s1[1]);
  143. Xor(s2[2], msg[32..], s1[2]);
  144. Xor(s2[3], msg[48..], s1[3]);
  145. s1[0].AsSpan(8, 8).CopyTo(output);
  146. s1[1].AsSpan(8, 8).CopyTo(output[8..]);
  147. s1[2].AsSpan(0, 8).CopyTo(output[16..]);
  148. s1[3].AsSpan(0, 8).CopyTo(output[24..]);
  149. return DIGEST_SIZE;
  150. }
  151. #else
  152. private static int Haraka512256(byte[] msg, byte[] output, int outOff)
  153. {
  154. byte[][] s1 = new byte[4][];
  155. s1[0] = new byte[16];
  156. s1[1] = new byte[16];
  157. s1[2] = new byte[16];
  158. s1[3] = new byte[16];
  159. byte[][] s2 = new byte[4][];
  160. s2[0] = new byte[16];
  161. s2[1] = new byte[16];
  162. s2[2] = new byte[16];
  163. s2[3] = new byte[16];
  164. Array.Copy(msg, 0, s1[0], 0, 16);
  165. Array.Copy(msg, 16, s1[1], 0, 16);
  166. Array.Copy(msg, 32, s1[2], 0, 16);
  167. Array.Copy(msg, 48, s1[3], 0, 16);
  168. s1[0] = AesEnc(s1[0], RC[0]);
  169. s1[1] = AesEnc(s1[1], RC[1]);
  170. s1[2] = AesEnc(s1[2], RC[2]);
  171. s1[3] = AesEnc(s1[3], RC[3]);
  172. s1[0] = AesEnc(s1[0], RC[4]);
  173. s1[1] = AesEnc(s1[1], RC[5]);
  174. s1[2] = AesEnc(s1[2], RC[6]);
  175. s1[3] = AesEnc(s1[3], RC[7]);
  176. Mix512(s1, s2);
  177. s1[0] = AesEnc(s2[0], RC[8]);
  178. s1[1] = AesEnc(s2[1], RC[9]);
  179. s1[2] = AesEnc(s2[2], RC[10]);
  180. s1[3] = AesEnc(s2[3], RC[11]);
  181. s1[0] = AesEnc(s1[0], RC[12]);
  182. s1[1] = AesEnc(s1[1], RC[13]);
  183. s1[2] = AesEnc(s1[2], RC[14]);
  184. s1[3] = AesEnc(s1[3], RC[15]);
  185. Mix512(s1, s2);
  186. s1[0] = AesEnc(s2[0], RC[16]);
  187. s1[1] = AesEnc(s2[1], RC[17]);
  188. s1[2] = AesEnc(s2[2], RC[18]);
  189. s1[3] = AesEnc(s2[3], RC[19]);
  190. s1[0] = AesEnc(s1[0], RC[20]);
  191. s1[1] = AesEnc(s1[1], RC[21]);
  192. s1[2] = AesEnc(s1[2], RC[22]);
  193. s1[3] = AesEnc(s1[3], RC[23]);
  194. Mix512(s1, s2);
  195. s1[0] = AesEnc(s2[0], RC[24]);
  196. s1[1] = AesEnc(s2[1], RC[25]);
  197. s1[2] = AesEnc(s2[2], RC[26]);
  198. s1[3] = AesEnc(s2[3], RC[27]);
  199. s1[0] = AesEnc(s1[0], RC[28]);
  200. s1[1] = AesEnc(s1[1], RC[29]);
  201. s1[2] = AesEnc(s1[2], RC[30]);
  202. s1[3] = AesEnc(s1[3], RC[31]);
  203. Mix512(s1, s2);
  204. s1[0] = AesEnc(s2[0], RC[32]);
  205. s1[1] = AesEnc(s2[1], RC[33]);
  206. s1[2] = AesEnc(s2[2], RC[34]);
  207. s1[3] = AesEnc(s2[3], RC[35]);
  208. s1[0] = AesEnc(s1[0], RC[36]);
  209. s1[1] = AesEnc(s1[1], RC[37]);
  210. s1[2] = AesEnc(s1[2], RC[38]);
  211. s1[3] = AesEnc(s1[3], RC[39]);
  212. Mix512(s1, s2);
  213. s1[0] = Xor(s2[0], msg, 0);
  214. s1[1] = Xor(s2[1], msg, 16);
  215. s1[2] = Xor(s2[2], msg, 32);
  216. s1[3] = Xor(s2[3], msg, 48);
  217. Array.Copy(s1[0], 8, output, outOff, 8);
  218. Array.Copy(s1[1], 8, output, outOff + 8, 8);
  219. Array.Copy(s1[2], 0, output, outOff + 16, 8);
  220. Array.Copy(s1[3], 0, output, outOff + 24, 8);
  221. return DIGEST_SIZE;
  222. }
  223. #endif
  224. private static void Mix512(byte[][] s1, byte[][] s2)
  225. {
  226. Array.Copy(s1[0], 12, s2[0], 0, 4);
  227. Array.Copy(s1[2], 12, s2[0], 4, 4);
  228. Array.Copy(s1[1], 12, s2[0], 8, 4);
  229. Array.Copy(s1[3], 12, s2[0], 12, 4);
  230. Array.Copy(s1[2], 0, s2[1], 0, 4);
  231. Array.Copy(s1[0], 0, s2[1], 4, 4);
  232. Array.Copy(s1[3], 0, s2[1], 8, 4);
  233. Array.Copy(s1[1], 0, s2[1], 12, 4);
  234. Array.Copy(s1[2], 4, s2[2], 0, 4);
  235. Array.Copy(s1[0], 4, s2[2], 4, 4);
  236. Array.Copy(s1[3], 4, s2[2], 8, 4);
  237. Array.Copy(s1[1], 4, s2[2], 12, 4);
  238. Array.Copy(s1[0], 8, s2[3], 0, 4);
  239. Array.Copy(s1[2], 8, s2[3], 4, 4);
  240. Array.Copy(s1[1], 8, s2[3], 8, 4);
  241. Array.Copy(s1[3], 8, s2[3], 12, 4);
  242. }
  243. }
  244. }
  245. #pragma warning restore
  246. #endif