MD4Digest.cs 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
  2. using System;
  3. using Org.BouncyCastle.Utilities;
  4. namespace Org.BouncyCastle.Crypto.Digests
  5. {
  6. /**
  7. * implementation of MD4 as RFC 1320 by R. Rivest, MIT Laboratory for
  8. * Computer Science and RSA Data Security, Inc.
  9. * <p>
  10. * <b>NOTE</b>: This algorithm is only included for backwards compatibility
  11. * with legacy applications, it's not secure, don't use it for anything new!</p>
  12. */
  13. public class MD4Digest
  14. : GeneralDigest
  15. {
  16. private const int DigestLength = 16;
  17. private int H1, H2, H3, H4; // IV's
  18. private int[] X = new int[16];
  19. private int xOff;
  20. /**
  21. * Standard constructor
  22. */
  23. public MD4Digest()
  24. {
  25. Reset();
  26. }
  27. /**
  28. * Copy constructor. This will copy the state of the provided
  29. * message digest.
  30. */
  31. public MD4Digest(MD4Digest t) : base(t)
  32. {
  33. CopyIn(t);
  34. }
  35. private void CopyIn(MD4Digest t)
  36. {
  37. base.CopyIn(t);
  38. H1 = t.H1;
  39. H2 = t.H2;
  40. H3 = t.H3;
  41. H4 = t.H4;
  42. Array.Copy(t.X, 0, X, 0, t.X.Length);
  43. xOff = t.xOff;
  44. }
  45. public override string AlgorithmName
  46. {
  47. get { return "MD4"; }
  48. }
  49. public override int GetDigestSize()
  50. {
  51. return DigestLength;
  52. }
  53. internal override void ProcessWord(
  54. byte[] input,
  55. int inOff)
  56. {
  57. X[xOff++] = (input[inOff] & 0xff) | ((input[inOff + 1] & 0xff) << 8)
  58. | ((input[inOff + 2] & 0xff) << 16) | ((input[inOff + 3] & 0xff) << 24);
  59. if (xOff == 16)
  60. {
  61. ProcessBlock();
  62. }
  63. }
  64. internal override void ProcessLength(
  65. long bitLength)
  66. {
  67. if (xOff > 14)
  68. {
  69. ProcessBlock();
  70. }
  71. X[14] = (int)(bitLength & 0xffffffff);
  72. X[15] = (int)((ulong) bitLength >> 32);
  73. }
  74. private void UnpackWord(
  75. int word,
  76. byte[] outBytes,
  77. int outOff)
  78. {
  79. outBytes[outOff] = (byte)word;
  80. outBytes[outOff + 1] = (byte)((uint) word >> 8);
  81. outBytes[outOff + 2] = (byte)((uint) word >> 16);
  82. outBytes[outOff + 3] = (byte)((uint) word >> 24);
  83. }
  84. public override int DoFinal(
  85. byte[] output,
  86. int outOff)
  87. {
  88. Finish();
  89. UnpackWord(H1, output, outOff);
  90. UnpackWord(H2, output, outOff + 4);
  91. UnpackWord(H3, output, outOff + 8);
  92. UnpackWord(H4, output, outOff + 12);
  93. Reset();
  94. return DigestLength;
  95. }
  96. /**
  97. * reset the chaining variables to the IV values.
  98. */
  99. public override void Reset()
  100. {
  101. base.Reset();
  102. H1 = unchecked((int) 0x67452301);
  103. H2 = unchecked((int) 0xefcdab89);
  104. H3 = unchecked((int) 0x98badcfe);
  105. H4 = unchecked((int) 0x10325476);
  106. xOff = 0;
  107. for (int i = 0; i != X.Length; i++)
  108. {
  109. X[i] = 0;
  110. }
  111. }
  112. //
  113. // round 1 left rotates
  114. //
  115. private const int S11 = 3;
  116. private const int S12 = 7;
  117. private const int S13 = 11;
  118. private const int S14 = 19;
  119. //
  120. // round 2 left rotates
  121. //
  122. private const int S21 = 3;
  123. private const int S22 = 5;
  124. private const int S23 = 9;
  125. private const int S24 = 13;
  126. //
  127. // round 3 left rotates
  128. //
  129. private const int S31 = 3;
  130. private const int S32 = 9;
  131. private const int S33 = 11;
  132. private const int S34 = 15;
  133. /*
  134. * rotate int x left n bits.
  135. */
  136. private int RotateLeft(
  137. int x,
  138. int n)
  139. {
  140. return (x << n) | (int) ((uint) x >> (32 - n));
  141. }
  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 = RotateLeft((a + F(b, c, d) + X[ 0]), S11);
  176. d = RotateLeft((d + F(a, b, c) + X[ 1]), S12);
  177. c = RotateLeft((c + F(d, a, b) + X[ 2]), S13);
  178. b = RotateLeft((b + F(c, d, a) + X[ 3]), S14);
  179. a = RotateLeft((a + F(b, c, d) + X[ 4]), S11);
  180. d = RotateLeft((d + F(a, b, c) + X[ 5]), S12);
  181. c = RotateLeft((c + F(d, a, b) + X[ 6]), S13);
  182. b = RotateLeft((b + F(c, d, a) + X[ 7]), S14);
  183. a = RotateLeft((a + F(b, c, d) + X[ 8]), S11);
  184. d = RotateLeft((d + F(a, b, c) + X[ 9]), S12);
  185. c = RotateLeft((c + F(d, a, b) + X[10]), S13);
  186. b = RotateLeft((b + F(c, d, a) + X[11]), S14);
  187. a = RotateLeft((a + F(b, c, d) + X[12]), S11);
  188. d = RotateLeft((d + F(a, b, c) + X[13]), S12);
  189. c = RotateLeft((c + F(d, a, b) + X[14]), S13);
  190. b = RotateLeft((b + F(c, d, a) + X[15]), S14);
  191. //
  192. // Round 2 - G cycle, 16 times.
  193. //
  194. a = RotateLeft((a + G(b, c, d) + X[ 0] + 0x5a827999), S21);
  195. d = RotateLeft((d + G(a, b, c) + X[ 4] + 0x5a827999), S22);
  196. c = RotateLeft((c + G(d, a, b) + X[ 8] + 0x5a827999), S23);
  197. b = RotateLeft((b + G(c, d, a) + X[12] + 0x5a827999), S24);
  198. a = RotateLeft((a + G(b, c, d) + X[ 1] + 0x5a827999), S21);
  199. d = RotateLeft((d + G(a, b, c) + X[ 5] + 0x5a827999), S22);
  200. c = RotateLeft((c + G(d, a, b) + X[ 9] + 0x5a827999), S23);
  201. b = RotateLeft((b + G(c, d, a) + X[13] + 0x5a827999), S24);
  202. a = RotateLeft((a + G(b, c, d) + X[ 2] + 0x5a827999), S21);
  203. d = RotateLeft((d + G(a, b, c) + X[ 6] + 0x5a827999), S22);
  204. c = RotateLeft((c + G(d, a, b) + X[10] + 0x5a827999), S23);
  205. b = RotateLeft((b + G(c, d, a) + X[14] + 0x5a827999), S24);
  206. a = RotateLeft((a + G(b, c, d) + X[ 3] + 0x5a827999), S21);
  207. d = RotateLeft((d + G(a, b, c) + X[ 7] + 0x5a827999), S22);
  208. c = RotateLeft((c + G(d, a, b) + X[11] + 0x5a827999), S23);
  209. b = RotateLeft((b + G(c, d, a) + X[15] + 0x5a827999), S24);
  210. //
  211. // Round 3 - H cycle, 16 times.
  212. //
  213. a = RotateLeft((a + H(b, c, d) + X[ 0] + 0x6ed9eba1), S31);
  214. d = RotateLeft((d + H(a, b, c) + X[ 8] + 0x6ed9eba1), S32);
  215. c = RotateLeft((c + H(d, a, b) + X[ 4] + 0x6ed9eba1), S33);
  216. b = RotateLeft((b + H(c, d, a) + X[12] + 0x6ed9eba1), S34);
  217. a = RotateLeft((a + H(b, c, d) + X[ 2] + 0x6ed9eba1), S31);
  218. d = RotateLeft((d + H(a, b, c) + X[10] + 0x6ed9eba1), S32);
  219. c = RotateLeft((c + H(d, a, b) + X[ 6] + 0x6ed9eba1), S33);
  220. b = RotateLeft((b + H(c, d, a) + X[14] + 0x6ed9eba1), S34);
  221. a = RotateLeft((a + H(b, c, d) + X[ 1] + 0x6ed9eba1), S31);
  222. d = RotateLeft((d + H(a, b, c) + X[ 9] + 0x6ed9eba1), S32);
  223. c = RotateLeft((c + H(d, a, b) + X[ 5] + 0x6ed9eba1), S33);
  224. b = RotateLeft((b + H(c, d, a) + X[13] + 0x6ed9eba1), S34);
  225. a = RotateLeft((a + H(b, c, d) + X[ 3] + 0x6ed9eba1), S31);
  226. d = RotateLeft((d + H(a, b, c) + X[11] + 0x6ed9eba1), S32);
  227. c = RotateLeft((c + H(d, a, b) + X[ 7] + 0x6ed9eba1), S33);
  228. b = 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. #endif