NoekeonEngine.cs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414
  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. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Utilities;
  6. using Best.HTTP.SecureProtocol.Org.BouncyCastle.Utilities;
  7. namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Engines
  8. {
  9. /**
  10. * A Noekeon engine, using direct-key mode.
  11. */
  12. public class NoekeonEngine
  13. : IBlockCipher
  14. {
  15. // Block and key size, as well as the amount of rounds.
  16. private const int Size = 16;
  17. private static readonly byte[] RoundConstants = { 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e,
  18. 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4 };
  19. private readonly uint[] k = new uint[4];
  20. private bool _initialised, _forEncryption;
  21. /**
  22. * Create an instance of the Noekeon encryption algorithm
  23. * and set some defaults
  24. */
  25. public NoekeonEngine()
  26. {
  27. _initialised = false;
  28. }
  29. public virtual string AlgorithmName
  30. {
  31. get { return "Noekeon"; }
  32. }
  33. public virtual int GetBlockSize()
  34. {
  35. return Size;
  36. }
  37. /**
  38. * initialise
  39. *
  40. * @param forEncryption whether or not we are for encryption.
  41. * @param params the parameters required to set up the cipher.
  42. * @exception ArgumentException if the params argument is
  43. * inappropriate.
  44. */
  45. public virtual void Init(bool forEncryption, ICipherParameters parameters)
  46. {
  47. if (!(parameters is KeyParameter))
  48. throw new ArgumentException("Invalid parameters passed to Noekeon init - "
  49. + Org.BouncyCastle.Utilities.Platform.GetTypeName(parameters), "parameters");
  50. KeyParameter p = (KeyParameter) parameters;
  51. byte[] key = p.GetKey();
  52. if (key.Length != 16)
  53. throw new ArgumentException("Key length not 128 bits.");
  54. Pack.BE_To_UInt32(key, 0, k, 0, 4);
  55. if (!forEncryption)
  56. {
  57. // theta(k, new uint[]{ 0x00, 0x00, 0x00, 0x00 });
  58. {
  59. uint a0 = k[0], a1 = k[1], a2 = k[2], a3 = k[3];
  60. uint t02 = a0 ^ a2;
  61. t02 ^= Integers.RotateLeft(t02, 8) ^ Integers.RotateLeft(t02, 24);
  62. uint t13 = a1 ^ a3;
  63. t13 ^= Integers.RotateLeft(t13, 8) ^ Integers.RotateLeft(t13, 24);
  64. a0 ^= t13;
  65. a1 ^= t02;
  66. a2 ^= t13;
  67. a3 ^= t02;
  68. k[0] = a0; k[1] = a1; k[2] = a2; k[3] = a3;
  69. }
  70. }
  71. this._forEncryption = forEncryption;
  72. this._initialised = true;
  73. }
  74. public virtual int ProcessBlock(byte[] input, int inOff, byte[] output, int outOff)
  75. {
  76. if (!_initialised)
  77. throw new InvalidOperationException(AlgorithmName + " not initialised");
  78. Check.DataLength(input, inOff, Size, "input buffer too short");
  79. Check.OutputLength(output, outOff, Size, "output buffer too short");
  80. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  81. return _forEncryption
  82. ? EncryptBlock(input.AsSpan(inOff), output.AsSpan(outOff))
  83. : DecryptBlock(input.AsSpan(inOff), output.AsSpan(outOff));
  84. #else
  85. return _forEncryption
  86. ? EncryptBlock(input, inOff, output, outOff)
  87. : DecryptBlock(input, inOff, output, outOff);
  88. #endif
  89. }
  90. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  91. public virtual int ProcessBlock(ReadOnlySpan<byte> input, Span<byte> output)
  92. {
  93. if (!_initialised)
  94. throw new InvalidOperationException(AlgorithmName + " not initialised");
  95. Check.DataLength(input, Size, "input buffer too short");
  96. Check.OutputLength(output, Size, "output buffer too short");
  97. return _forEncryption
  98. ? EncryptBlock(input, output)
  99. : DecryptBlock(input, output);
  100. }
  101. #endif
  102. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  103. private int EncryptBlock(ReadOnlySpan<byte> input, Span<byte> output)
  104. {
  105. uint a0 = Pack.BE_To_UInt32(input);
  106. uint a1 = Pack.BE_To_UInt32(input[4..]);
  107. uint a2 = Pack.BE_To_UInt32(input[8..]);
  108. uint a3 = Pack.BE_To_UInt32(input[12..]);
  109. uint k0 = k[0], k1 = k[1], k2 = k[2], k3 = k[3];
  110. int round = 0;
  111. for (;;)
  112. {
  113. a0 ^= RoundConstants[round];
  114. // theta(a, k);
  115. {
  116. uint t02 = a0 ^ a2;
  117. t02 ^= Integers.RotateLeft(t02, 8) ^ Integers.RotateLeft(t02, 24);
  118. a0 ^= k0;
  119. a1 ^= k1;
  120. a2 ^= k2;
  121. a3 ^= k3;
  122. uint t13 = a1 ^ a3;
  123. t13 ^= Integers.RotateLeft(t13, 8) ^ Integers.RotateLeft(t13, 24);
  124. a0 ^= t13;
  125. a1 ^= t02;
  126. a2 ^= t13;
  127. a3 ^= t02;
  128. }
  129. if (++round > Size)
  130. break;
  131. // pi1(a);
  132. {
  133. a1 = Integers.RotateLeft(a1, 1);
  134. a2 = Integers.RotateLeft(a2, 5);
  135. a3 = Integers.RotateLeft(a3, 2);
  136. }
  137. // gamma(a);
  138. {
  139. uint t = a3;
  140. a1 ^= a3 | a2;
  141. a3 = a0 ^ (a2 & ~a1);
  142. a2 = t ^ ~a1 ^ a2 ^ a3;
  143. a1 ^= a3 | a2;
  144. a0 = t ^ (a2 & a1);
  145. }
  146. // pi2(a);
  147. {
  148. a1 = Integers.RotateLeft(a1, 31);
  149. a2 = Integers.RotateLeft(a2, 27);
  150. a3 = Integers.RotateLeft(a3, 30);
  151. }
  152. }
  153. Pack.UInt32_To_BE(a0, output);
  154. Pack.UInt32_To_BE(a1, output[4..]);
  155. Pack.UInt32_To_BE(a2, output[8..]);
  156. Pack.UInt32_To_BE(a3, output[12..]);
  157. return Size;
  158. }
  159. private int DecryptBlock(ReadOnlySpan<byte> input, Span<byte> output)
  160. {
  161. uint a0 = Pack.BE_To_UInt32(input);
  162. uint a1 = Pack.BE_To_UInt32(input[4..]);
  163. uint a2 = Pack.BE_To_UInt32(input[8..]);
  164. uint a3 = Pack.BE_To_UInt32(input[12..]);
  165. uint k0 = k[0], k1 = k[1], k2 = k[2], k3 = k[3];
  166. int round = Size;
  167. for (;;)
  168. {
  169. // theta(a, k);
  170. {
  171. uint t02 = a0 ^ a2;
  172. t02 ^= Integers.RotateLeft(t02, 8) ^ Integers.RotateLeft(t02, 24);
  173. a0 ^= k0;
  174. a1 ^= k1;
  175. a2 ^= k2;
  176. a3 ^= k3;
  177. uint t13 = a1 ^ a3;
  178. t13 ^= Integers.RotateLeft(t13, 8) ^ Integers.RotateLeft(t13, 24);
  179. a0 ^= t13;
  180. a1 ^= t02;
  181. a2 ^= t13;
  182. a3 ^= t02;
  183. }
  184. a0 ^= RoundConstants[round];
  185. if (--round < 0)
  186. break;
  187. // pi1(a);
  188. {
  189. a1 = Integers.RotateLeft(a1, 1);
  190. a2 = Integers.RotateLeft(a2, 5);
  191. a3 = Integers.RotateLeft(a3, 2);
  192. }
  193. // gamma(a);
  194. {
  195. uint t = a3;
  196. a1 ^= a3 | a2;
  197. a3 = a0 ^ (a2 & ~a1);
  198. a2 = t ^ ~a1 ^ a2 ^ a3;
  199. a1 ^= a3 | a2;
  200. a0 = t ^ (a2 & a1);
  201. }
  202. // pi2(a);
  203. {
  204. a1 = Integers.RotateLeft(a1, 31);
  205. a2 = Integers.RotateLeft(a2, 27);
  206. a3 = Integers.RotateLeft(a3, 30);
  207. }
  208. }
  209. Pack.UInt32_To_BE(a0, output);
  210. Pack.UInt32_To_BE(a1, output[4..]);
  211. Pack.UInt32_To_BE(a2, output[8..]);
  212. Pack.UInt32_To_BE(a3, output[12..]);
  213. return Size;
  214. }
  215. #else
  216. private int EncryptBlock(byte[] input, int inOff, byte[] output, int outOff)
  217. {
  218. uint a0 = Pack.BE_To_UInt32(input, inOff);
  219. uint a1 = Pack.BE_To_UInt32(input, inOff + 4);
  220. uint a2 = Pack.BE_To_UInt32(input, inOff + 8);
  221. uint a3 = Pack.BE_To_UInt32(input, inOff + 12);
  222. uint k0 = k[0], k1 = k[1], k2 = k[2], k3 = k[3];
  223. int round = 0;
  224. for (;;)
  225. {
  226. a0 ^= RoundConstants[round];
  227. // theta(a, k);
  228. {
  229. uint t02 = a0 ^ a2;
  230. t02 ^= Integers.RotateLeft(t02, 8) ^ Integers.RotateLeft(t02, 24);
  231. a0 ^= k0;
  232. a1 ^= k1;
  233. a2 ^= k2;
  234. a3 ^= k3;
  235. uint t13 = a1 ^ a3;
  236. t13 ^= Integers.RotateLeft(t13, 8) ^ Integers.RotateLeft(t13, 24);
  237. a0 ^= t13;
  238. a1 ^= t02;
  239. a2 ^= t13;
  240. a3 ^= t02;
  241. }
  242. if (++round > Size)
  243. break;
  244. // pi1(a);
  245. {
  246. a1 = Integers.RotateLeft(a1, 1);
  247. a2 = Integers.RotateLeft(a2, 5);
  248. a3 = Integers.RotateLeft(a3, 2);
  249. }
  250. // gamma(a);
  251. {
  252. uint t = a3;
  253. a1 ^= a3 | a2;
  254. a3 = a0 ^ (a2 & ~a1);
  255. a2 = t ^ ~a1 ^ a2 ^ a3;
  256. a1 ^= a3 | a2;
  257. a0 = t ^ (a2 & a1);
  258. }
  259. // pi2(a);
  260. {
  261. a1 = Integers.RotateLeft(a1, 31);
  262. a2 = Integers.RotateLeft(a2, 27);
  263. a3 = Integers.RotateLeft(a3, 30);
  264. }
  265. }
  266. Pack.UInt32_To_BE(a0, output, outOff);
  267. Pack.UInt32_To_BE(a1, output, outOff + 4);
  268. Pack.UInt32_To_BE(a2, output, outOff + 8);
  269. Pack.UInt32_To_BE(a3, output, outOff + 12);
  270. return Size;
  271. }
  272. private int DecryptBlock(byte[] input, int inOff, byte[] output, int outOff)
  273. {
  274. uint a0 = Pack.BE_To_UInt32(input, inOff);
  275. uint a1 = Pack.BE_To_UInt32(input, inOff + 4);
  276. uint a2 = Pack.BE_To_UInt32(input, inOff + 8);
  277. uint a3 = Pack.BE_To_UInt32(input, inOff + 12);
  278. uint k0 = k[0], k1 = k[1], k2 = k[2], k3 = k[3];
  279. int round = Size;
  280. for (;;)
  281. {
  282. // theta(a, k);
  283. {
  284. uint t02 = a0 ^ a2;
  285. t02 ^= Integers.RotateLeft(t02, 8) ^ Integers.RotateLeft(t02, 24);
  286. a0 ^= k0;
  287. a1 ^= k1;
  288. a2 ^= k2;
  289. a3 ^= k3;
  290. uint t13 = a1 ^ a3;
  291. t13 ^= Integers.RotateLeft(t13, 8) ^ Integers.RotateLeft(t13, 24);
  292. a0 ^= t13;
  293. a1 ^= t02;
  294. a2 ^= t13;
  295. a3 ^= t02;
  296. }
  297. a0 ^= RoundConstants[round];
  298. if (--round < 0)
  299. break;
  300. // pi1(a);
  301. {
  302. a1 = Integers.RotateLeft(a1, 1);
  303. a2 = Integers.RotateLeft(a2, 5);
  304. a3 = Integers.RotateLeft(a3, 2);
  305. }
  306. // gamma(a);
  307. {
  308. uint t = a3;
  309. a1 ^= a3 | a2;
  310. a3 = a0 ^ (a2 & ~a1);
  311. a2 = t ^ ~a1 ^ a2 ^ a3;
  312. a1 ^= a3 | a2;
  313. a0 = t ^ (a2 & a1);
  314. }
  315. // pi2(a);
  316. {
  317. a1 = Integers.RotateLeft(a1, 31);
  318. a2 = Integers.RotateLeft(a2, 27);
  319. a3 = Integers.RotateLeft(a3, 30);
  320. }
  321. }
  322. Pack.UInt32_To_BE(a0, output, outOff);
  323. Pack.UInt32_To_BE(a1, output, outOff + 4);
  324. Pack.UInt32_To_BE(a2, output, outOff + 8);
  325. Pack.UInt32_To_BE(a3, output, outOff + 12);
  326. return Size;
  327. }
  328. #endif
  329. }
  330. }
  331. #pragma warning restore
  332. #endif