HC256Engine.cs 5.2 KB

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