HC128Engine.cs 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
  2. #pragma warning disable
  3. using System;
  4. using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Parameters;
  5. using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Utilities;
  6. using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities;
  7. namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Engines
  8. {
  9. /**
  10. * HC-128 is a software-efficient stream cipher created by Hongjun Wu. It
  11. * generates keystream from a 128-bit secret key and a 128-bit initialization
  12. * vector.
  13. * <p>
  14. * http://www.ecrypt.eu.org/stream/p3ciphers/hc/hc128_p3.pdf
  15. * </p><p>
  16. * It is a third phase candidate in the eStream contest, and is patent-free.
  17. * No attacks are known as of today (April 2007). See
  18. *
  19. * http://www.ecrypt.eu.org/stream/hcp3.html
  20. * </p>
  21. */
  22. public class HC128Engine
  23. : IStreamCipher
  24. {
  25. private uint[] p = new uint[512];
  26. private uint[] q = new uint[512];
  27. private uint cnt = 0;
  28. private static uint F1(uint x)
  29. {
  30. return RotateRight(x, 7) ^ RotateRight(x, 18) ^ (x >> 3);
  31. }
  32. private static uint F2(uint x)
  33. {
  34. return RotateRight(x, 17) ^ RotateRight(x, 19) ^ (x >> 10);
  35. }
  36. private uint G1(uint x, uint y, uint z)
  37. {
  38. return (RotateRight(x, 10) ^ RotateRight(z, 23)) + RotateRight(y, 8);
  39. }
  40. private uint G2(uint x, uint y, uint z)
  41. {
  42. return (RotateLeft(x, 10) ^ RotateLeft(z, 23)) + RotateLeft(y, 8);
  43. }
  44. private static uint RotateLeft(uint x, int bits)
  45. {
  46. return (x << bits) | (x >> -bits);
  47. }
  48. private static uint RotateRight(uint x, int bits)
  49. {
  50. return (x >> bits) | (x << -bits);
  51. }
  52. private uint H1(uint x)
  53. {
  54. return q[x & 0xFF] + q[((x >> 16) & 0xFF) + 256];
  55. }
  56. private uint H2(uint x)
  57. {
  58. return p[x & 0xFF] + p[((x >> 16) & 0xFF) + 256];
  59. }
  60. private static uint Mod1024(uint x)
  61. {
  62. return x & 0x3FF;
  63. }
  64. private static uint Mod512(uint x)
  65. {
  66. return x & 0x1FF;
  67. }
  68. private static uint Dim(uint x, uint y)
  69. {
  70. return Mod512(x - y);
  71. }
  72. private uint Step()
  73. {
  74. uint j = Mod512(cnt);
  75. uint ret;
  76. if (cnt < 512)
  77. {
  78. p[j] += G1(p[Dim(j, 3)], p[Dim(j, 10)], p[Dim(j, 511)]);
  79. ret = H1(p[Dim(j, 12)]) ^ p[j];
  80. }
  81. else
  82. {
  83. q[j] += G2(q[Dim(j, 3)], q[Dim(j, 10)], q[Dim(j, 511)]);
  84. ret = H2(q[Dim(j, 12)]) ^ q[j];
  85. }
  86. cnt = Mod1024(cnt + 1);
  87. return ret;
  88. }
  89. private byte[] key, iv;
  90. private bool initialised;
  91. private void Init()
  92. {
  93. if (key.Length != 16)
  94. throw new ArgumentException("The key must be 128 bits long");
  95. idx = 0;
  96. cnt = 0;
  97. uint[] w = new uint[1280];
  98. for (int i = 0; i < 16; i++)
  99. {
  100. w[i >> 2] |= ((uint)key[i] << (8 * (i & 0x3)));
  101. }
  102. Array.Copy(w, 0, w, 4, 4);
  103. for (int i = 0; i < iv.Length && i < 16; i++)
  104. {
  105. w[(i >> 2) + 8] |= ((uint)iv[i] << (8 * (i & 0x3)));
  106. }
  107. Array.Copy(w, 8, w, 12, 4);
  108. for (uint i = 16; i < 1280; i++)
  109. {
  110. w[i] = F2(w[i - 2]) + w[i - 7] + F1(w[i - 15]) + w[i - 16] + i;
  111. }
  112. Array.Copy(w, 256, p, 0, 512);
  113. Array.Copy(w, 768, q, 0, 512);
  114. for (int i = 0; i < 512; i++)
  115. {
  116. p[i] = Step();
  117. }
  118. for (int i = 0; i < 512; i++)
  119. {
  120. q[i] = Step();
  121. }
  122. cnt = 0;
  123. }
  124. public virtual string AlgorithmName
  125. {
  126. get { return "HC-128"; }
  127. }
  128. /**
  129. * Initialise a HC-128 cipher.
  130. *
  131. * @param forEncryption whether or not we are for encryption. Irrelevant, as
  132. * encryption and decryption are the same.
  133. * @param params the parameters required to set up the cipher.
  134. * @throws ArgumentException if the params argument is
  135. * inappropriate (ie. the key is not 128 bit long).
  136. */
  137. public virtual void Init(
  138. bool forEncryption,
  139. ICipherParameters parameters)
  140. {
  141. ICipherParameters keyParam = parameters;
  142. if (parameters is ParametersWithIV)
  143. {
  144. iv = ((ParametersWithIV)parameters).GetIV();
  145. keyParam = ((ParametersWithIV)parameters).Parameters;
  146. }
  147. else
  148. {
  149. iv = new byte[0];
  150. }
  151. if (keyParam is KeyParameter)
  152. {
  153. key = ((KeyParameter)keyParam).GetKey();
  154. Init();
  155. }
  156. else
  157. {
  158. throw new ArgumentException(
  159. "Invalid parameter passed to HC128 init - " + BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.Platform.GetTypeName(parameters),
  160. "parameters");
  161. }
  162. initialised = true;
  163. }
  164. private byte[] buf = new byte[4];
  165. private int idx = 0;
  166. private byte GetByte()
  167. {
  168. if (idx == 0)
  169. {
  170. Pack.UInt32_To_LE(Step(), buf);
  171. }
  172. byte ret = buf[idx];
  173. idx = idx + 1 & 0x3;
  174. return ret;
  175. }
  176. public virtual void ProcessBytes(
  177. byte[] input,
  178. int inOff,
  179. int len,
  180. byte[] output,
  181. int outOff)
  182. {
  183. if (!initialised)
  184. throw new InvalidOperationException(AlgorithmName + " not initialised");
  185. Check.DataLength(input, inOff, len, "input buffer too short");
  186. Check.OutputLength(output, outOff, len, "output buffer too short");
  187. for (int i = 0; i < len; i++)
  188. {
  189. output[outOff + i] = (byte)(input[inOff + i] ^ GetByte());
  190. }
  191. }
  192. public virtual void Reset()
  193. {
  194. Init();
  195. }
  196. public virtual byte ReturnByte(byte input)
  197. {
  198. return (byte)(input ^ GetByte());
  199. }
  200. }
  201. }
  202. #pragma warning restore
  203. #endif