MD2Digest.cs 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  1. #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
  2. #pragma warning disable
  3. using System;
  4. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Utilities;
  5. namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Digests
  6. {
  7. /**
  8. * implementation of MD2
  9. * as outlined in RFC1319 by B.Kaliski from RSA Laboratories April 1992
  10. */
  11. public class MD2Digest
  12. : IDigest, IMemoable
  13. {
  14. private const int DigestLength = 16;
  15. private const int BYTE_LENGTH = 16;
  16. /* X buffer */
  17. private byte[] X = new byte[48];
  18. private int xOff;
  19. /* M buffer */
  20. private byte[] M = new byte[16];
  21. private int mOff;
  22. /* check sum */
  23. private byte[] C = new byte[16];
  24. private int COff;
  25. public MD2Digest()
  26. {
  27. Reset();
  28. }
  29. public MD2Digest(MD2Digest t)
  30. {
  31. CopyIn(t);
  32. }
  33. private void CopyIn(MD2Digest t)
  34. {
  35. Array.Copy(t.X, 0, X, 0, t.X.Length);
  36. xOff = t.xOff;
  37. Array.Copy(t.M, 0, M, 0, t.M.Length);
  38. mOff = t.mOff;
  39. Array.Copy(t.C, 0, C, 0, t.C.Length);
  40. COff = t.COff;
  41. }
  42. /**
  43. * return the algorithm name
  44. *
  45. * @return the algorithm name
  46. */
  47. public string AlgorithmName
  48. {
  49. get { return "MD2"; }
  50. }
  51. public int GetDigestSize()
  52. {
  53. return DigestLength;
  54. }
  55. public int GetByteLength()
  56. {
  57. return BYTE_LENGTH;
  58. }
  59. /**
  60. * Close the digest, producing the final digest value. The doFinal
  61. * call leaves the digest reset.
  62. *
  63. * @param out the array the digest is to be copied into.
  64. * @param outOff the offset into the out array the digest is to start at.
  65. */
  66. public int DoFinal(byte[] output, int outOff)
  67. {
  68. // add padding
  69. byte paddingByte = (byte)(M.Length - mOff);
  70. for (int i=mOff;i<M.Length;i++)
  71. {
  72. M[i] = paddingByte;
  73. }
  74. //do final check sum
  75. ProcessChecksum(M);
  76. // do final block process
  77. ProcessBlock(M);
  78. ProcessBlock(C);
  79. Array.Copy(X, xOff, output, outOff, 16);
  80. Reset();
  81. return DigestLength;
  82. }
  83. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  84. public int DoFinal(Span<byte> output)
  85. {
  86. // add padding
  87. byte paddingByte = (byte)(M.Length - mOff);
  88. for (int i = mOff; i < M.Length; i++)
  89. {
  90. M[i] = paddingByte;
  91. }
  92. //do final check sum
  93. ProcessChecksum(M);
  94. // do final block process
  95. ProcessBlock(M);
  96. ProcessBlock(C);
  97. X.AsSpan(xOff, 16).CopyTo(output);
  98. Reset();
  99. return DigestLength;
  100. }
  101. #endif
  102. /**
  103. * reset the digest back to it's initial state.
  104. */
  105. public void Reset()
  106. {
  107. xOff = 0;
  108. for (int i = 0; i != X.Length; i++)
  109. {
  110. X[i] = 0;
  111. }
  112. mOff = 0;
  113. for (int i = 0; i != M.Length; i++)
  114. {
  115. M[i] = 0;
  116. }
  117. COff = 0;
  118. for (int i = 0; i != C.Length; i++)
  119. {
  120. C[i] = 0;
  121. }
  122. }
  123. /**
  124. * update the message digest with a single byte.
  125. *
  126. * @param in the input byte to be entered.
  127. */
  128. public void Update(byte input)
  129. {
  130. M[mOff++] = input;
  131. if (mOff == 16)
  132. {
  133. ProcessChecksum(M);
  134. ProcessBlock(M);
  135. mOff = 0;
  136. }
  137. }
  138. /**
  139. * update the message digest with a block of bytes.
  140. *
  141. * @param in the byte array containing the data.
  142. * @param inOff the offset into the byte array where the data starts.
  143. * @param len the length of the data.
  144. */
  145. public void BlockUpdate(byte[] input, int inOff, int length)
  146. {
  147. //
  148. // fill the current word
  149. //
  150. while ((mOff != 0) && (length > 0))
  151. {
  152. Update(input[inOff]);
  153. inOff++;
  154. length--;
  155. }
  156. //
  157. // process whole words.
  158. //
  159. while (length >= 16)
  160. {
  161. Array.Copy(input,inOff,M,0,16);
  162. ProcessChecksum(M);
  163. ProcessBlock(M);
  164. length -= 16;
  165. inOff += 16;
  166. }
  167. //
  168. // load in the remainder.
  169. //
  170. while (length > 0)
  171. {
  172. Update(input[inOff]);
  173. inOff++;
  174. length--;
  175. }
  176. }
  177. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  178. public void BlockUpdate(ReadOnlySpan<byte> input)
  179. {
  180. //
  181. // fill the current word
  182. //
  183. while ((mOff != 0) && (input.Length > 0))
  184. {
  185. Update(input[0]);
  186. input = input[1..];
  187. }
  188. //
  189. // process whole words.
  190. //
  191. while (input.Length >= 16)
  192. {
  193. input[..16].CopyTo(M);
  194. ProcessChecksum(M);
  195. ProcessBlock(M);
  196. input = input[16..];
  197. }
  198. //
  199. // load in the remainder.
  200. //
  201. while (input.Length > 0)
  202. {
  203. Update(input[0]);
  204. input = input[1..];
  205. }
  206. }
  207. #endif
  208. internal void ProcessChecksum(byte[] m)
  209. {
  210. int L = C[15];
  211. for (int i=0;i<16;i++)
  212. {
  213. C[i] ^= S[(m[i] ^ L) & 0xff];
  214. L = C[i];
  215. }
  216. }
  217. internal void ProcessBlock(byte[] m)
  218. {
  219. for (int i=0;i<16;i++)
  220. {
  221. X[i+16] = m[i];
  222. X[i+32] = (byte)(m[i] ^ X[i]);
  223. }
  224. // encrypt block
  225. int t = 0;
  226. for (int j=0;j<18;j++)
  227. {
  228. for (int k=0;k<48;k++)
  229. {
  230. t = X[k] ^= S[t];
  231. t = t & 0xff;
  232. }
  233. t = (t + j)%256;
  234. }
  235. }
  236. // 256-byte random permutation constructed from the digits of PI
  237. private static readonly byte[] S = {
  238. (byte)41,(byte)46,(byte)67,(byte)201,(byte)162,(byte)216,(byte)124,
  239. (byte)1,(byte)61,(byte)54,(byte)84,(byte)161,(byte)236,(byte)240,
  240. (byte)6,(byte)19,(byte)98,(byte)167,(byte)5,(byte)243,(byte)192,
  241. (byte)199,(byte)115,(byte)140,(byte)152,(byte)147,(byte)43,(byte)217,
  242. (byte)188,(byte)76,(byte)130,(byte)202,(byte)30,(byte)155,(byte)87,
  243. (byte)60,(byte)253,(byte)212,(byte)224,(byte)22,(byte)103,(byte)66,
  244. (byte)111,(byte)24,(byte)138,(byte)23,(byte)229,(byte)18,(byte)190,
  245. (byte)78,(byte)196,(byte)214,(byte)218,(byte)158,(byte)222,(byte)73,
  246. (byte)160,(byte)251,(byte)245,(byte)142,(byte)187,(byte)47,(byte)238,
  247. (byte)122,(byte)169,(byte)104,(byte)121,(byte)145,(byte)21,(byte)178,
  248. (byte)7,(byte)63,(byte)148,(byte)194,(byte)16,(byte)137,(byte)11,
  249. (byte)34,(byte)95,(byte)33,(byte)128,(byte)127,(byte)93,(byte)154,
  250. (byte)90,(byte)144,(byte)50,(byte)39,(byte)53,(byte)62,(byte)204,
  251. (byte)231,(byte)191,(byte)247,(byte)151,(byte)3,(byte)255,(byte)25,
  252. (byte)48,(byte)179,(byte)72,(byte)165,(byte)181,(byte)209,(byte)215,
  253. (byte)94,(byte)146,(byte)42,(byte)172,(byte)86,(byte)170,(byte)198,
  254. (byte)79,(byte)184,(byte)56,(byte)210,(byte)150,(byte)164,(byte)125,
  255. (byte)182,(byte)118,(byte)252,(byte)107,(byte)226,(byte)156,(byte)116,
  256. (byte)4,(byte)241,(byte)69,(byte)157,(byte)112,(byte)89,(byte)100,
  257. (byte)113,(byte)135,(byte)32,(byte)134,(byte)91,(byte)207,(byte)101,
  258. (byte)230,(byte)45,(byte)168,(byte)2,(byte)27,(byte)96,(byte)37,
  259. (byte)173,(byte)174,(byte)176,(byte)185,(byte)246,(byte)28,(byte)70,
  260. (byte)97,(byte)105,(byte)52,(byte)64,(byte)126,(byte)15,(byte)85,
  261. (byte)71,(byte)163,(byte)35,(byte)221,(byte)81,(byte)175,(byte)58,
  262. (byte)195,(byte)92,(byte)249,(byte)206,(byte)186,(byte)197,(byte)234,
  263. (byte)38,(byte)44,(byte)83,(byte)13,(byte)110,(byte)133,(byte)40,
  264. (byte)132, 9,(byte)211,(byte)223,(byte)205,(byte)244,(byte)65,
  265. (byte)129,(byte)77,(byte)82,(byte)106,(byte)220,(byte)55,(byte)200,
  266. (byte)108,(byte)193,(byte)171,(byte)250,(byte)36,(byte)225,(byte)123,
  267. (byte)8,(byte)12,(byte)189,(byte)177,(byte)74,(byte)120,(byte)136,
  268. (byte)149,(byte)139,(byte)227,(byte)99,(byte)232,(byte)109,(byte)233,
  269. (byte)203,(byte)213,(byte)254,(byte)59,(byte)0,(byte)29,(byte)57,
  270. (byte)242,(byte)239,(byte)183,(byte)14,(byte)102,(byte)88,(byte)208,
  271. (byte)228,(byte)166,(byte)119,(byte)114,(byte)248,(byte)235,(byte)117,
  272. (byte)75,(byte)10,(byte)49,(byte)68,(byte)80,(byte)180,(byte)143,
  273. (byte)237,(byte)31,(byte)26,(byte)219,(byte)153,(byte)141,(byte)51,
  274. (byte)159,(byte)17,(byte)131,(byte)20
  275. };
  276. public IMemoable Copy()
  277. {
  278. return new MD2Digest(this);
  279. }
  280. public void Reset(IMemoable other)
  281. {
  282. MD2Digest d = (MD2Digest)other;
  283. CopyIn(d);
  284. }
  285. }
  286. }
  287. #pragma warning restore
  288. #endif