VMPCMac.cs 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  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.Parameters;
  5. namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Macs
  6. {
  7. public class VmpcMac
  8. : IMac
  9. {
  10. private byte g;
  11. private byte n = 0;
  12. private byte[] P = null;
  13. private byte s = 0;
  14. private byte[] T;
  15. private byte[] workingIV;
  16. private byte[] workingKey;
  17. private byte x1, x2, x3, x4;
  18. public virtual int DoFinal(byte[] output, int outOff)
  19. {
  20. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  21. return DoFinal(output.AsSpan(outOff));
  22. #else
  23. // Execute the Post-Processing Phase
  24. for (int r = 1; r < 25; r++)
  25. {
  26. s = P[(s + P[n & 0xff]) & 0xff];
  27. x4 = P[(x4 + x3 + r) & 0xff];
  28. x3 = P[(x3 + x2 + r) & 0xff];
  29. x2 = P[(x2 + x1 + r) & 0xff];
  30. x1 = P[(x1 + s + r) & 0xff];
  31. T[g & 0x1f] = (byte) (T[g & 0x1f] ^ x1);
  32. T[(g + 1) & 0x1f] = (byte) (T[(g + 1) & 0x1f] ^ x2);
  33. T[(g + 2) & 0x1f] = (byte) (T[(g + 2) & 0x1f] ^ x3);
  34. T[(g + 3) & 0x1f] = (byte) (T[(g + 3) & 0x1f] ^ x4);
  35. g = (byte) ((g + 4) & 0x1f);
  36. byte temp = P[n & 0xff];
  37. P[n & 0xff] = P[s & 0xff];
  38. P[s & 0xff] = temp;
  39. n = (byte) ((n + 1) & 0xff);
  40. }
  41. // Input T to the IV-phase of the VMPC KSA
  42. for (int m = 0; m < 768; m++)
  43. {
  44. s = P[(s + P[m & 0xff] + T[m & 0x1f]) & 0xff];
  45. byte temp = P[m & 0xff];
  46. P[m & 0xff] = P[s & 0xff];
  47. P[s & 0xff] = temp;
  48. }
  49. // Store 20 new outputs of the VMPC Stream Cipher input table M
  50. byte[] M = new byte[20];
  51. for (int i = 0; i < 20; i++)
  52. {
  53. s = P[(s + P[i & 0xff]) & 0xff];
  54. M[i] = P[(P[(P[s & 0xff]) & 0xff] + 1) & 0xff];
  55. byte temp = P[i & 0xff];
  56. P[i & 0xff] = P[s & 0xff];
  57. P[s & 0xff] = temp;
  58. }
  59. Array.Copy(M, 0, output, outOff, M.Length);
  60. Reset();
  61. return M.Length;
  62. #endif
  63. }
  64. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  65. public virtual int DoFinal(Span<byte> output)
  66. {
  67. // Execute the Post-Processing Phase
  68. for (int r = 1; r < 25; r++)
  69. {
  70. s = P[(s + P[n & 0xff]) & 0xff];
  71. x4 = P[(x4 + x3 + r) & 0xff];
  72. x3 = P[(x3 + x2 + r) & 0xff];
  73. x2 = P[(x2 + x1 + r) & 0xff];
  74. x1 = P[(x1 + s + r) & 0xff];
  75. T[g & 0x1f] = (byte)(T[g & 0x1f] ^ x1);
  76. T[(g + 1) & 0x1f] = (byte)(T[(g + 1) & 0x1f] ^ x2);
  77. T[(g + 2) & 0x1f] = (byte)(T[(g + 2) & 0x1f] ^ x3);
  78. T[(g + 3) & 0x1f] = (byte)(T[(g + 3) & 0x1f] ^ x4);
  79. g = (byte)((g + 4) & 0x1f);
  80. byte temp = P[n & 0xff];
  81. P[n & 0xff] = P[s & 0xff];
  82. P[s & 0xff] = temp;
  83. n = (byte)((n + 1) & 0xff);
  84. }
  85. // Input T to the IV-phase of the VMPC KSA
  86. for (int m = 0; m < 768; m++)
  87. {
  88. s = P[(s + P[m & 0xff] + T[m & 0x1f]) & 0xff];
  89. byte temp = P[m & 0xff];
  90. P[m & 0xff] = P[s & 0xff];
  91. P[s & 0xff] = temp;
  92. }
  93. // Store 20 new outputs of the VMPC Stream Cipher input table M
  94. byte[] M = new byte[20];
  95. for (int i = 0; i < 20; i++)
  96. {
  97. s = P[(s + P[i & 0xff]) & 0xff];
  98. M[i] = P[(P[(P[s & 0xff]) & 0xff] + 1) & 0xff];
  99. byte temp = P[i & 0xff];
  100. P[i & 0xff] = P[s & 0xff];
  101. P[s & 0xff] = temp;
  102. }
  103. M.CopyTo(output);
  104. Reset();
  105. return M.Length;
  106. }
  107. #endif
  108. public virtual string AlgorithmName
  109. {
  110. get { return "VMPC-MAC"; }
  111. }
  112. public virtual int GetMacSize()
  113. {
  114. return 20;
  115. }
  116. public virtual void Init(ICipherParameters parameters)
  117. {
  118. if (!(parameters is ParametersWithIV))
  119. throw new ArgumentException("VMPC-MAC Init parameters must include an IV", "parameters");
  120. ParametersWithIV ivParams = (ParametersWithIV) parameters;
  121. KeyParameter key = (KeyParameter) ivParams.Parameters;
  122. if (!(ivParams.Parameters is KeyParameter))
  123. throw new ArgumentException("VMPC-MAC Init parameters must include a key", "parameters");
  124. this.workingIV = ivParams.GetIV();
  125. if (workingIV == null || workingIV.Length < 1 || workingIV.Length > 768)
  126. throw new ArgumentException("VMPC-MAC requires 1 to 768 bytes of IV", "parameters");
  127. this.workingKey = key.GetKey();
  128. Reset();
  129. }
  130. private void initKey(byte[] keyBytes, byte[] ivBytes)
  131. {
  132. s = 0;
  133. P = new byte[256];
  134. for (int i = 0; i < 256; i++)
  135. {
  136. P[i] = (byte) i;
  137. }
  138. for (int m = 0; m < 768; m++)
  139. {
  140. s = P[(s + P[m & 0xff] + keyBytes[m % keyBytes.Length]) & 0xff];
  141. byte temp = P[m & 0xff];
  142. P[m & 0xff] = P[s & 0xff];
  143. P[s & 0xff] = temp;
  144. }
  145. for (int m = 0; m < 768; m++)
  146. {
  147. s = P[(s + P[m & 0xff] + ivBytes[m % ivBytes.Length]) & 0xff];
  148. byte temp = P[m & 0xff];
  149. P[m & 0xff] = P[s & 0xff];
  150. P[s & 0xff] = temp;
  151. }
  152. n = 0;
  153. }
  154. public virtual void Reset()
  155. {
  156. initKey(this.workingKey, this.workingIV);
  157. g = x1 = x2 = x3 = x4 = n = 0;
  158. T = new byte[32];
  159. for (int i = 0; i < 32; i++)
  160. {
  161. T[i] = 0;
  162. }
  163. }
  164. public virtual void Update(byte input)
  165. {
  166. s = P[(s + P[n & 0xff]) & 0xff];
  167. byte c = (byte) (input ^ P[(P[(P[s & 0xff]) & 0xff] + 1) & 0xff]);
  168. x4 = P[(x4 + x3) & 0xff];
  169. x3 = P[(x3 + x2) & 0xff];
  170. x2 = P[(x2 + x1) & 0xff];
  171. x1 = P[(x1 + s + c) & 0xff];
  172. T[g & 0x1f] = (byte) (T[g & 0x1f] ^ x1);
  173. T[(g + 1) & 0x1f] = (byte) (T[(g + 1) & 0x1f] ^ x2);
  174. T[(g + 2) & 0x1f] = (byte) (T[(g + 2) & 0x1f] ^ x3);
  175. T[(g + 3) & 0x1f] = (byte) (T[(g + 3) & 0x1f] ^ x4);
  176. g = (byte) ((g + 4) & 0x1f);
  177. byte temp = P[n & 0xff];
  178. P[n & 0xff] = P[s & 0xff];
  179. P[s & 0xff] = temp;
  180. n = (byte) ((n + 1) & 0xff);
  181. }
  182. public virtual void BlockUpdate(byte[] input, int inOff, int inLen)
  183. {
  184. Check.DataLength(input, inOff, inLen, "input buffer too short");
  185. for (int i = 0; i < inLen; i++)
  186. {
  187. Update(input[inOff + i]);
  188. }
  189. }
  190. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  191. public virtual void BlockUpdate(ReadOnlySpan<byte> input)
  192. {
  193. for (int i = 0; i < input.Length; i++)
  194. {
  195. Update(input[i]);
  196. }
  197. }
  198. #endif
  199. }
  200. }
  201. #pragma warning restore
  202. #endif