Cast6Engine.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  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.Utilities;
  5. namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.Engines
  6. {
  7. /**
  8. * A class that provides CAST6 key encryption operations,
  9. * such as encoding data and generating keys.
  10. *
  11. * All the algorithms herein are from the Internet RFC
  12. *
  13. * RFC2612 - CAST6 (128bit block, 128-256bit key)
  14. *
  15. * and implement a simplified cryptography interface.
  16. */
  17. public sealed class Cast6Engine
  18. : Cast5Engine
  19. {
  20. //====================================
  21. // Useful constants
  22. //====================================
  23. private const int ROUNDS = 12;
  24. private const int BLOCK_SIZE = 16; // bytes = 128 bits
  25. /*
  26. * Put the round and mask keys into an array.
  27. * Kr0[i] => _Kr[i*4 + 0]
  28. */
  29. private int []_Kr = new int[ROUNDS*4]; // the rotating round key(s)
  30. private uint []_Km = new uint[ROUNDS*4]; // the masking round key(s)
  31. /*
  32. * Key setup
  33. */
  34. private int []_Tr = new int[24 * 8];
  35. private uint []_Tm = new uint[24 * 8];
  36. private uint[] _workingKey = new uint[8];
  37. public Cast6Engine()
  38. {
  39. }
  40. public override string AlgorithmName
  41. {
  42. get { return "CAST6"; }
  43. }
  44. public override int GetBlockSize()
  45. {
  46. return BLOCK_SIZE;
  47. }
  48. //==================================
  49. // Private Implementation
  50. //==================================
  51. /*
  52. * Creates the subkeys using the same nomenclature
  53. * as described in RFC2612.
  54. *
  55. * See section 2.4
  56. */
  57. internal override void SetKey(
  58. byte[] key)
  59. {
  60. uint Cm = 0x5a827999;
  61. uint Mm = 0x6ed9eba1;
  62. int Cr = 19;
  63. int Mr = 17;
  64. /*
  65. * Determine the key size here, if required
  66. *
  67. * if keysize < 256 bytes, pad with 0
  68. *
  69. * Typical key sizes => 128, 160, 192, 224, 256
  70. */
  71. for (int i=0; i< 24; i++)
  72. {
  73. for (int j=0; j< 8; j++)
  74. {
  75. _Tm[i*8 + j] = Cm;
  76. Cm += Mm; //mod 2^32;
  77. _Tr[i*8 + j] = Cr;
  78. Cr = (Cr + Mr) & 0x1f; // mod 32
  79. }
  80. }
  81. byte[] tmpKey = new byte[64];
  82. key.CopyTo(tmpKey, 0);
  83. // now create ABCDEFGH
  84. for (int i = 0; i < 8; i++)
  85. {
  86. _workingKey[i] = Pack.BE_To_UInt32(tmpKey, i*4);
  87. }
  88. // Generate the key schedule
  89. for (int i = 0; i < 12; i++)
  90. {
  91. // KAPPA <- W2i(KAPPA)
  92. int i2 = i*2 *8;
  93. _workingKey[6] ^= F1(_workingKey[7], _Tm[i2], _Tr[i2]);
  94. _workingKey[5] ^= F2(_workingKey[6], _Tm[i2+1], _Tr[i2+1]);
  95. _workingKey[4] ^= F3(_workingKey[5], _Tm[i2+2], _Tr[i2+2]);
  96. _workingKey[3] ^= F1(_workingKey[4], _Tm[i2+3], _Tr[i2+3]);
  97. _workingKey[2] ^= F2(_workingKey[3], _Tm[i2+4], _Tr[i2+4]);
  98. _workingKey[1] ^= F3(_workingKey[2], _Tm[i2+5], _Tr[i2+5]);
  99. _workingKey[0] ^= F1(_workingKey[1], _Tm[i2+6], _Tr[i2+6]);
  100. _workingKey[7] ^= F2(_workingKey[0], _Tm[i2+7], _Tr[i2+7]);
  101. // KAPPA <- W2i+1(KAPPA)
  102. i2 = (i*2 + 1)*8;
  103. _workingKey[6] ^= F1(_workingKey[7], _Tm[i2], _Tr[i2]);
  104. _workingKey[5] ^= F2(_workingKey[6], _Tm[i2+1], _Tr[i2+1]);
  105. _workingKey[4] ^= F3(_workingKey[5], _Tm[i2+2], _Tr[i2+2]);
  106. _workingKey[3] ^= F1(_workingKey[4], _Tm[i2+3], _Tr[i2+3]);
  107. _workingKey[2] ^= F2(_workingKey[3], _Tm[i2+4], _Tr[i2+4]);
  108. _workingKey[1] ^= F3(_workingKey[2], _Tm[i2+5], _Tr[i2+5]);
  109. _workingKey[0] ^= F1(_workingKey[1], _Tm[i2+6], _Tr[i2+6]);
  110. _workingKey[7] ^= F2(_workingKey[0], _Tm[i2+7], _Tr[i2+7]);
  111. // Kr_(i) <- KAPPA
  112. _Kr[i*4] = (int)(_workingKey[0] & 0x1f);
  113. _Kr[i*4 + 1] = (int)(_workingKey[2] & 0x1f);
  114. _Kr[i*4 + 2] = (int)(_workingKey[4] & 0x1f);
  115. _Kr[i*4 + 3] = (int)(_workingKey[6] & 0x1f);
  116. // Km_(i) <- KAPPA
  117. _Km[i*4] = _workingKey[7];
  118. _Km[i*4 + 1] = _workingKey[5];
  119. _Km[i*4 + 2] = _workingKey[3];
  120. _Km[i*4 + 3] = _workingKey[1];
  121. }
  122. }
  123. #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
  124. internal override int EncryptBlock(ReadOnlySpan<byte> input, Span<byte> output)
  125. {
  126. // process the input block
  127. // batch the units up into 4x32 bit chunks and go for it
  128. uint A = Pack.BE_To_UInt32(input);
  129. uint B = Pack.BE_To_UInt32(input[4..]);
  130. uint C = Pack.BE_To_UInt32(input[8..]);
  131. uint D = Pack.BE_To_UInt32(input[12..]);
  132. uint[] result = new uint[4];
  133. CAST_Encipher(A, B, C, D, result);
  134. // now stuff them into the destination block
  135. Pack.UInt32_To_BE(result[0], output);
  136. Pack.UInt32_To_BE(result[1], output[4..]);
  137. Pack.UInt32_To_BE(result[2], output[8..]);
  138. Pack.UInt32_To_BE(result[3], output[12..]);
  139. return BLOCK_SIZE;
  140. }
  141. internal override int DecryptBlock(ReadOnlySpan<byte> input, Span<byte> output)
  142. {
  143. // process the input block
  144. // batch the units up into 4x32 bit chunks and go for it
  145. uint A = Pack.BE_To_UInt32(input);
  146. uint B = Pack.BE_To_UInt32(input[4..]);
  147. uint C = Pack.BE_To_UInt32(input[8..]);
  148. uint D = Pack.BE_To_UInt32(input[12..]);
  149. uint[] result = new uint[4];
  150. CAST_Decipher(A, B, C, D, result);
  151. // now stuff them into the destination block
  152. Pack.UInt32_To_BE(result[0], output);
  153. Pack.UInt32_To_BE(result[1], output[4..]);
  154. Pack.UInt32_To_BE(result[2], output[8..]);
  155. Pack.UInt32_To_BE(result[3], output[12..]);
  156. return BLOCK_SIZE;
  157. }
  158. #else
  159. internal override int EncryptBlock(byte[] src, int srcIndex, byte[] dst, int dstIndex)
  160. {
  161. // process the input block
  162. // batch the units up into 4x32 bit chunks and go for it
  163. uint A = Pack.BE_To_UInt32(src, srcIndex);
  164. uint B = Pack.BE_To_UInt32(src, srcIndex + 4);
  165. uint C = Pack.BE_To_UInt32(src, srcIndex + 8);
  166. uint D = Pack.BE_To_UInt32(src, srcIndex + 12);
  167. uint[] result = new uint[4];
  168. CAST_Encipher(A, B, C, D, result);
  169. // now stuff them into the destination block
  170. Pack.UInt32_To_BE(result[0], dst, dstIndex);
  171. Pack.UInt32_To_BE(result[1], dst, dstIndex + 4);
  172. Pack.UInt32_To_BE(result[2], dst, dstIndex + 8);
  173. Pack.UInt32_To_BE(result[3], dst, dstIndex + 12);
  174. return BLOCK_SIZE;
  175. }
  176. internal override int DecryptBlock(byte[] src, int srcIndex, byte[] dst, int dstIndex)
  177. {
  178. // process the input block
  179. // batch the units up into 4x32 bit chunks and go for it
  180. uint A = Pack.BE_To_UInt32(src, srcIndex);
  181. uint B = Pack.BE_To_UInt32(src, srcIndex + 4);
  182. uint C = Pack.BE_To_UInt32(src, srcIndex + 8);
  183. uint D = Pack.BE_To_UInt32(src, srcIndex + 12);
  184. uint[] result = new uint[4];
  185. CAST_Decipher(A, B, C, D, result);
  186. // now stuff them into the destination block
  187. Pack.UInt32_To_BE(result[0], dst, dstIndex);
  188. Pack.UInt32_To_BE(result[1], dst, dstIndex + 4);
  189. Pack.UInt32_To_BE(result[2], dst, dstIndex + 8);
  190. Pack.UInt32_To_BE(result[3], dst, dstIndex + 12);
  191. return BLOCK_SIZE;
  192. }
  193. #endif
  194. /**
  195. * Does the 12 quad rounds rounds to encrypt the block.
  196. *
  197. * @param A the 00-31 bits of the plaintext block
  198. * @param B the 32-63 bits of the plaintext block
  199. * @param C the 64-95 bits of the plaintext block
  200. * @param D the 96-127 bits of the plaintext block
  201. * @param result the resulting ciphertext
  202. */
  203. private void CAST_Encipher(
  204. uint A,
  205. uint B,
  206. uint C,
  207. uint D,
  208. uint[] result)
  209. {
  210. for (int i = 0; i < 6; i++)
  211. {
  212. int x = i*4;
  213. // BETA <- Qi(BETA)
  214. C ^= F1(D, _Km[x], _Kr[x]);
  215. B ^= F2(C, _Km[x + 1], _Kr[x + 1]);
  216. A ^= F3(B, _Km[x + 2], _Kr[x + 2]);
  217. D ^= F1(A, _Km[x + 3], _Kr[x + 3]);
  218. }
  219. for (int i = 6; i < 12; i++)
  220. {
  221. int x = i*4;
  222. // BETA <- QBARi(BETA)
  223. D ^= F1(A, _Km[x + 3], _Kr[x + 3]);
  224. A ^= F3(B, _Km[x + 2], _Kr[x + 2]);
  225. B ^= F2(C, _Km[x + 1], _Kr[x + 1]);
  226. C ^= F1(D, _Km[x], _Kr[x]);
  227. }
  228. result[0] = A;
  229. result[1] = B;
  230. result[2] = C;
  231. result[3] = D;
  232. }
  233. /**
  234. * Does the 12 quad rounds rounds to decrypt the block.
  235. *
  236. * @param A the 00-31 bits of the ciphertext block
  237. * @param B the 32-63 bits of the ciphertext block
  238. * @param C the 64-95 bits of the ciphertext block
  239. * @param D the 96-127 bits of the ciphertext block
  240. * @param result the resulting plaintext
  241. */
  242. private void CAST_Decipher(
  243. uint A,
  244. uint B,
  245. uint C,
  246. uint D,
  247. uint[] result)
  248. {
  249. for (int i = 0; i < 6; i++)
  250. {
  251. int x = (11-i)*4;
  252. // BETA <- Qi(BETA)
  253. C ^= F1(D, _Km[x], _Kr[x]);
  254. B ^= F2(C, _Km[x + 1], _Kr[x + 1]);
  255. A ^= F3(B, _Km[x + 2], _Kr[x + 2]);
  256. D ^= F1(A, _Km[x + 3], _Kr[x + 3]);
  257. }
  258. for (int i=6; i<12; i++)
  259. {
  260. int x = (11-i)*4;
  261. // BETA <- QBARi(BETA)
  262. D ^= F1(A, _Km[x + 3], _Kr[x + 3]);
  263. A ^= F3(B, _Km[x + 2], _Kr[x + 2]);
  264. B ^= F2(C, _Km[x + 1], _Kr[x + 1]);
  265. C ^= F1(D, _Km[x], _Kr[x]);
  266. }
  267. result[0] = A;
  268. result[1] = B;
  269. result[2] = C;
  270. result[3] = D;
  271. }
  272. }
  273. }
  274. #pragma warning restore
  275. #endif