NoekeonEngine.cs 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  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. * A Noekeon engine, using direct-key mode.
  11. */
  12. public class NoekeonEngine
  13. : IBlockCipher
  14. {
  15. private const int GenericSize = 16; // Block and key size, as well as the amount of rounds.
  16. private static readonly uint[] nullVector =
  17. {
  18. 0x00, 0x00, 0x00, 0x00 // Used in decryption
  19. };
  20. private static readonly uint[] roundConstants =
  21. {
  22. 0x80, 0x1b, 0x36, 0x6c,
  23. 0xd8, 0xab, 0x4d, 0x9a,
  24. 0x2f, 0x5e, 0xbc, 0x63,
  25. 0xc6, 0x97, 0x35, 0x6a,
  26. 0xd4
  27. };
  28. private uint[] state = new uint[4], // a
  29. subKeys = new uint[4], // k
  30. decryptKeys = new uint[4];
  31. private bool _initialised, _forEncryption;
  32. /**
  33. * Create an instance of the Noekeon encryption algorithm
  34. * and set some defaults
  35. */
  36. public NoekeonEngine()
  37. {
  38. _initialised = false;
  39. }
  40. public virtual string AlgorithmName
  41. {
  42. get { return "Noekeon"; }
  43. }
  44. public virtual bool IsPartialBlockOkay
  45. {
  46. get { return false; }
  47. }
  48. public virtual int GetBlockSize()
  49. {
  50. return GenericSize;
  51. }
  52. /**
  53. * initialise
  54. *
  55. * @param forEncryption whether or not we are for encryption.
  56. * @param params the parameters required to set up the cipher.
  57. * @exception ArgumentException if the params argument is
  58. * inappropriate.
  59. */
  60. public virtual void Init(
  61. bool forEncryption,
  62. ICipherParameters parameters)
  63. {
  64. if (!(parameters is KeyParameter))
  65. throw new ArgumentException("Invalid parameters passed to Noekeon init - "
  66. + BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.Platform.GetTypeName(parameters), "parameters");
  67. _forEncryption = forEncryption;
  68. _initialised = true;
  69. KeyParameter p = (KeyParameter) parameters;
  70. setKey(p.GetKey());
  71. }
  72. public virtual int ProcessBlock(
  73. byte[] input,
  74. int inOff,
  75. byte[] output,
  76. int outOff)
  77. {
  78. if (!_initialised)
  79. throw new InvalidOperationException(AlgorithmName + " not initialised");
  80. Check.DataLength(input, inOff, GenericSize, "input buffer too short");
  81. Check.OutputLength(output, outOff, GenericSize, "output buffer too short");
  82. return _forEncryption
  83. ? encryptBlock(input, inOff, output, outOff)
  84. : decryptBlock(input, inOff, output, outOff);
  85. }
  86. public virtual void Reset()
  87. {
  88. // TODO This should do something in case the encryption is aborted
  89. }
  90. /**
  91. * Re-key the cipher.
  92. *
  93. * @param key the key to be used
  94. */
  95. private void setKey(byte[] key)
  96. {
  97. subKeys[0] = Pack.BE_To_UInt32(key, 0);
  98. subKeys[1] = Pack.BE_To_UInt32(key, 4);
  99. subKeys[2] = Pack.BE_To_UInt32(key, 8);
  100. subKeys[3] = Pack.BE_To_UInt32(key, 12);
  101. }
  102. private int encryptBlock(
  103. byte[] input,
  104. int inOff,
  105. byte[] output,
  106. int outOff)
  107. {
  108. state[0] = Pack.BE_To_UInt32(input, inOff);
  109. state[1] = Pack.BE_To_UInt32(input, inOff+4);
  110. state[2] = Pack.BE_To_UInt32(input, inOff+8);
  111. state[3] = Pack.BE_To_UInt32(input, inOff+12);
  112. int i;
  113. for (i = 0; i < GenericSize; i++)
  114. {
  115. state[0] ^= roundConstants[i];
  116. theta(state, subKeys);
  117. pi1(state);
  118. gamma(state);
  119. pi2(state);
  120. }
  121. state[0] ^= roundConstants[i];
  122. theta(state, subKeys);
  123. Pack.UInt32_To_BE(state[0], output, outOff);
  124. Pack.UInt32_To_BE(state[1], output, outOff+4);
  125. Pack.UInt32_To_BE(state[2], output, outOff+8);
  126. Pack.UInt32_To_BE(state[3], output, outOff+12);
  127. return GenericSize;
  128. }
  129. private int decryptBlock(
  130. byte[] input,
  131. int inOff,
  132. byte[] output,
  133. int outOff)
  134. {
  135. state[0] = Pack.BE_To_UInt32(input, inOff);
  136. state[1] = Pack.BE_To_UInt32(input, inOff+4);
  137. state[2] = Pack.BE_To_UInt32(input, inOff+8);
  138. state[3] = Pack.BE_To_UInt32(input, inOff+12);
  139. Array.Copy(subKeys, 0, decryptKeys, 0, subKeys.Length);
  140. theta(decryptKeys, nullVector);
  141. int i;
  142. for (i = GenericSize; i > 0; i--)
  143. {
  144. theta(state, decryptKeys);
  145. state[0] ^= roundConstants[i];
  146. pi1(state);
  147. gamma(state);
  148. pi2(state);
  149. }
  150. theta(state, decryptKeys);
  151. state[0] ^= roundConstants[i];
  152. Pack.UInt32_To_BE(state[0], output, outOff);
  153. Pack.UInt32_To_BE(state[1], output, outOff+4);
  154. Pack.UInt32_To_BE(state[2], output, outOff+8);
  155. Pack.UInt32_To_BE(state[3], output, outOff+12);
  156. return GenericSize;
  157. }
  158. private void gamma(uint[] a)
  159. {
  160. a[1] ^= ~a[3] & ~a[2];
  161. a[0] ^= a[2] & a[1];
  162. uint tmp = a[3];
  163. a[3] = a[0];
  164. a[0] = tmp;
  165. a[2] ^= a[0]^a[1]^a[3];
  166. a[1] ^= ~a[3] & ~a[2];
  167. a[0] ^= a[2] & a[1];
  168. }
  169. private void theta(uint[] a, uint[] k)
  170. {
  171. uint tmp;
  172. tmp = a[0]^a[2];
  173. tmp ^= rotl(tmp,8)^rotl(tmp,24);
  174. a[1] ^= tmp;
  175. a[3] ^= tmp;
  176. for (int i = 0; i < 4; i++)
  177. {
  178. a[i] ^= k[i];
  179. }
  180. tmp = a[1]^a[3];
  181. tmp ^= rotl(tmp,8)^rotl(tmp,24);
  182. a[0] ^= tmp;
  183. a[2] ^= tmp;
  184. }
  185. private void pi1(uint[] a)
  186. {
  187. a[1] = rotl(a[1], 1);
  188. a[2] = rotl(a[2], 5);
  189. a[3] = rotl(a[3], 2);
  190. }
  191. private void pi2(uint[] a)
  192. {
  193. a[1] = rotl(a[1], 31);
  194. a[2] = rotl(a[2], 27);
  195. a[3] = rotl(a[3], 30);
  196. }
  197. // Helpers
  198. private uint rotl(uint x, int y)
  199. {
  200. return (x << y) | (x >> (32-y));
  201. }
  202. }
  203. }
  204. #pragma warning restore
  205. #endif