MD4Digest.cs 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
  2. #pragma warning disable
  3. using System;
  4. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Utilities;
  5. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Utilities;
  6. namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Digests
  7. {
  8. /**
  9. * implementation of MD4 as RFC 1320 by R. Rivest, MIT Laboratory for
  10. * Computer Science and RSA Data Security, Inc.
  11. * <p>
  12. * <b>NOTE</b>: This algorithm is only included for backwards compatibility
  13. * with legacy applications, it's not secure, don't use it for anything new!</p>
  14. */
  15. public class MD4Digest
  16. : GeneralDigest
  17. {
  18. private const int DigestLength = 16;
  19. private int H1, H2, H3, H4; // IV's
  20. private int[] X = new int[16];
  21. private int xOff;
  22. /**
  23. * Standard constructor
  24. */
  25. public MD4Digest()
  26. {
  27. Reset();
  28. }
  29. /**
  30. * Copy constructor. This will copy the state of the provided
  31. * message digest.
  32. */
  33. public MD4Digest(MD4Digest t) : base(t)
  34. {
  35. CopyIn(t);
  36. }
  37. private void CopyIn(MD4Digest t)
  38. {
  39. base.CopyIn(t);
  40. H1 = t.H1;
  41. H2 = t.H2;
  42. H3 = t.H3;
  43. H4 = t.H4;
  44. Array.Copy(t.X, 0, X, 0, t.X.Length);
  45. xOff = t.xOff;
  46. }
  47. public override string AlgorithmName
  48. {
  49. get { return "MD4"; }
  50. }
  51. public override int GetDigestSize()
  52. {
  53. return DigestLength;
  54. }
  55. internal override void ProcessWord(byte[] input, int inOff)
  56. {
  57. X[xOff++] = (int)Pack.LE_To_UInt32(input, inOff);
  58. if (xOff == 16)
  59. {
  60. ProcessBlock();
  61. }
  62. }
  63. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  64. internal override void ProcessWord(ReadOnlySpan<byte> word)
  65. {
  66. X[xOff++] = (int)Pack.LE_To_UInt32(word);
  67. if (xOff == 16)
  68. {
  69. ProcessBlock();
  70. }
  71. }
  72. #endif
  73. internal override void ProcessLength(
  74. long bitLength)
  75. {
  76. if (xOff > 14)
  77. {
  78. ProcessBlock();
  79. }
  80. X[14] = (int)(bitLength & 0xffffffff);
  81. X[15] = (int)((ulong) bitLength >> 32);
  82. }
  83. public override int DoFinal(byte[] output, int outOff)
  84. {
  85. Finish();
  86. Pack.UInt32_To_LE((uint)H1, output, outOff);
  87. Pack.UInt32_To_LE((uint)H2, output, outOff + 4);
  88. Pack.UInt32_To_LE((uint)H3, output, outOff + 8);
  89. Pack.UInt32_To_LE((uint)H4, output, outOff + 12);
  90. Reset();
  91. return DigestLength;
  92. }
  93. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  94. public override int DoFinal(Span<byte> output)
  95. {
  96. Finish();
  97. Pack.UInt32_To_LE((uint)H1, output);
  98. Pack.UInt32_To_LE((uint)H2, output[4..]);
  99. Pack.UInt32_To_LE((uint)H3, output[8..]);
  100. Pack.UInt32_To_LE((uint)H4, output[12..]);
  101. Reset();
  102. return DigestLength;
  103. }
  104. #endif
  105. /**
  106. * reset the chaining variables to the IV values.
  107. */
  108. public override void Reset()
  109. {
  110. base.Reset();
  111. H1 = unchecked((int) 0x67452301);
  112. H2 = unchecked((int) 0xefcdab89);
  113. H3 = unchecked((int) 0x98badcfe);
  114. H4 = unchecked((int) 0x10325476);
  115. xOff = 0;
  116. for (int i = 0; i != X.Length; i++)
  117. {
  118. X[i] = 0;
  119. }
  120. }
  121. //
  122. // round 1 left rotates
  123. //
  124. private const int S11 = 3;
  125. private const int S12 = 7;
  126. private const int S13 = 11;
  127. private const int S14 = 19;
  128. //
  129. // round 2 left rotates
  130. //
  131. private const int S21 = 3;
  132. private const int S22 = 5;
  133. private const int S23 = 9;
  134. private const int S24 = 13;
  135. //
  136. // round 3 left rotates
  137. //
  138. private const int S31 = 3;
  139. private const int S32 = 9;
  140. private const int S33 = 11;
  141. private const int S34 = 15;
  142. /*
  143. * F, G, H and I are the basic MD4 functions.
  144. */
  145. private int F(
  146. int u,
  147. int v,
  148. int w)
  149. {
  150. return (u & v) | (~u & w);
  151. }
  152. private int G(
  153. int u,
  154. int v,
  155. int w)
  156. {
  157. return (u & v) | (u & w) | (v & w);
  158. }
  159. private int H(
  160. int u,
  161. int v,
  162. int w)
  163. {
  164. return u ^ v ^ w;
  165. }
  166. internal override void ProcessBlock()
  167. {
  168. int a = H1;
  169. int b = H2;
  170. int c = H3;
  171. int d = H4;
  172. //
  173. // Round 1 - F cycle, 16 times.
  174. //
  175. a = Integers.RotateLeft((a + F(b, c, d) + X[ 0]), S11);
  176. d = Integers.RotateLeft((d + F(a, b, c) + X[ 1]), S12);
  177. c = Integers.RotateLeft((c + F(d, a, b) + X[ 2]), S13);
  178. b = Integers.RotateLeft((b + F(c, d, a) + X[ 3]), S14);
  179. a = Integers.RotateLeft((a + F(b, c, d) + X[ 4]), S11);
  180. d = Integers.RotateLeft((d + F(a, b, c) + X[ 5]), S12);
  181. c = Integers.RotateLeft((c + F(d, a, b) + X[ 6]), S13);
  182. b = Integers.RotateLeft((b + F(c, d, a) + X[ 7]), S14);
  183. a = Integers.RotateLeft((a + F(b, c, d) + X[ 8]), S11);
  184. d = Integers.RotateLeft((d + F(a, b, c) + X[ 9]), S12);
  185. c = Integers.RotateLeft((c + F(d, a, b) + X[10]), S13);
  186. b = Integers.RotateLeft((b + F(c, d, a) + X[11]), S14);
  187. a = Integers.RotateLeft((a + F(b, c, d) + X[12]), S11);
  188. d = Integers.RotateLeft((d + F(a, b, c) + X[13]), S12);
  189. c = Integers.RotateLeft((c + F(d, a, b) + X[14]), S13);
  190. b = Integers.RotateLeft((b + F(c, d, a) + X[15]), S14);
  191. //
  192. // Round 2 - G cycle, 16 times.
  193. //
  194. a = Integers.RotateLeft((a + G(b, c, d) + X[ 0] + 0x5a827999), S21);
  195. d = Integers.RotateLeft((d + G(a, b, c) + X[ 4] + 0x5a827999), S22);
  196. c = Integers.RotateLeft((c + G(d, a, b) + X[ 8] + 0x5a827999), S23);
  197. b = Integers.RotateLeft((b + G(c, d, a) + X[12] + 0x5a827999), S24);
  198. a = Integers.RotateLeft((a + G(b, c, d) + X[ 1] + 0x5a827999), S21);
  199. d = Integers.RotateLeft((d + G(a, b, c) + X[ 5] + 0x5a827999), S22);
  200. c = Integers.RotateLeft((c + G(d, a, b) + X[ 9] + 0x5a827999), S23);
  201. b = Integers.RotateLeft((b + G(c, d, a) + X[13] + 0x5a827999), S24);
  202. a = Integers.RotateLeft((a + G(b, c, d) + X[ 2] + 0x5a827999), S21);
  203. d = Integers.RotateLeft((d + G(a, b, c) + X[ 6] + 0x5a827999), S22);
  204. c = Integers.RotateLeft((c + G(d, a, b) + X[10] + 0x5a827999), S23);
  205. b = Integers.RotateLeft((b + G(c, d, a) + X[14] + 0x5a827999), S24);
  206. a = Integers.RotateLeft((a + G(b, c, d) + X[ 3] + 0x5a827999), S21);
  207. d = Integers.RotateLeft((d + G(a, b, c) + X[ 7] + 0x5a827999), S22);
  208. c = Integers.RotateLeft((c + G(d, a, b) + X[11] + 0x5a827999), S23);
  209. b = Integers.RotateLeft((b + G(c, d, a) + X[15] + 0x5a827999), S24);
  210. //
  211. // Round 3 - H cycle, 16 times.
  212. //
  213. a = Integers.RotateLeft((a + H(b, c, d) + X[ 0] + 0x6ed9eba1), S31);
  214. d = Integers.RotateLeft((d + H(a, b, c) + X[ 8] + 0x6ed9eba1), S32);
  215. c = Integers.RotateLeft((c + H(d, a, b) + X[ 4] + 0x6ed9eba1), S33);
  216. b = Integers.RotateLeft((b + H(c, d, a) + X[12] + 0x6ed9eba1), S34);
  217. a = Integers.RotateLeft((a + H(b, c, d) + X[ 2] + 0x6ed9eba1), S31);
  218. d = Integers.RotateLeft((d + H(a, b, c) + X[10] + 0x6ed9eba1), S32);
  219. c = Integers.RotateLeft((c + H(d, a, b) + X[ 6] + 0x6ed9eba1), S33);
  220. b = Integers.RotateLeft((b + H(c, d, a) + X[14] + 0x6ed9eba1), S34);
  221. a = Integers.RotateLeft((a + H(b, c, d) + X[ 1] + 0x6ed9eba1), S31);
  222. d = Integers.RotateLeft((d + H(a, b, c) + X[ 9] + 0x6ed9eba1), S32);
  223. c = Integers.RotateLeft((c + H(d, a, b) + X[ 5] + 0x6ed9eba1), S33);
  224. b = Integers.RotateLeft((b + H(c, d, a) + X[13] + 0x6ed9eba1), S34);
  225. a = Integers.RotateLeft((a + H(b, c, d) + X[ 3] + 0x6ed9eba1), S31);
  226. d = Integers.RotateLeft((d + H(a, b, c) + X[11] + 0x6ed9eba1), S32);
  227. c = Integers.RotateLeft((c + H(d, a, b) + X[ 7] + 0x6ed9eba1), S33);
  228. b = Integers.RotateLeft((b + H(c, d, a) + X[15] + 0x6ed9eba1), S34);
  229. H1 += a;
  230. H2 += b;
  231. H3 += c;
  232. H4 += d;
  233. //
  234. // reset the offset and clean out the word buffer.
  235. //
  236. xOff = 0;
  237. for (int i = 0; i != X.Length; i++)
  238. {
  239. X[i] = 0;
  240. }
  241. }
  242. public override IMemoable Copy()
  243. {
  244. return new MD4Digest(this);
  245. }
  246. public override void Reset(IMemoable other)
  247. {
  248. MD4Digest d = (MD4Digest)other;
  249. CopyIn(d);
  250. }
  251. }
  252. }
  253. #pragma warning restore
  254. #endif