Dstu7624Engine.cs 45 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088
  1. #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
  2. #pragma warning disable
  3. using System;
  4. using System.Collections;
  5. using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Parameters;
  6. using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Utilities;
  7. using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities;
  8. namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Engines
  9. {
  10. /**
  11. * implementation of DSTU 7624 (Kalyna)
  12. */
  13. public class Dstu7624Engine
  14. : IBlockCipher
  15. {
  16. private ulong[] internalState;
  17. private ulong[] workingKey;
  18. private ulong[][] roundKeys;
  19. /* Number of 64-bit words in block */
  20. private int wordsInBlock;
  21. /* Number of 64-bit words in key */
  22. private int wordsInKey;
  23. /* Number of encryption rounds depending on key length */
  24. private const int ROUNDS_128 = 10;
  25. private const int ROUNDS_256 = 14;
  26. private const int ROUNDS_512 = 18;
  27. private int roundsAmount;
  28. private bool forEncryption;
  29. public Dstu7624Engine(int blockSizeBits)
  30. {
  31. /* DSTU7624 supports 128 | 256 | 512 key/block sizes */
  32. if (blockSizeBits != 128 && blockSizeBits != 256 && blockSizeBits != 512)
  33. {
  34. throw new ArgumentException("unsupported block length: only 128/256/512 are allowed");
  35. }
  36. wordsInBlock = blockSizeBits / 64;
  37. internalState = new ulong[wordsInBlock];
  38. }
  39. #region INITIALIZATION
  40. public virtual void Init(bool forEncryption, ICipherParameters parameters)
  41. {
  42. if (!(parameters is KeyParameter))
  43. throw new ArgumentException("Invalid parameter passed to Dstu7624Engine Init");
  44. this.forEncryption = forEncryption;
  45. byte[] keyBytes = ((KeyParameter)parameters).GetKey();
  46. int keyBitLength = keyBytes.Length << 3;
  47. int blockBitLength = wordsInBlock << 6;
  48. if (keyBitLength != 128 && keyBitLength != 256 && keyBitLength != 512)
  49. {
  50. throw new ArgumentException("unsupported key length: only 128/256/512 are allowed");
  51. }
  52. /* Limitations on key lengths depending on block lengths. See table 6.1 in standard */
  53. if (keyBitLength != blockBitLength && keyBitLength != (2 * blockBitLength))
  54. {
  55. throw new ArgumentException("Unsupported key length");
  56. }
  57. switch (keyBitLength)
  58. {
  59. case 128:
  60. roundsAmount = ROUNDS_128;
  61. break;
  62. case 256:
  63. roundsAmount = ROUNDS_256;
  64. break;
  65. case 512:
  66. roundsAmount = ROUNDS_512;
  67. break;
  68. }
  69. wordsInKey = keyBitLength / 64;
  70. /* +1 round key as defined in standard */
  71. roundKeys = new ulong[roundsAmount + 1][];
  72. for (int roundKeyIndex = 0; roundKeyIndex < roundKeys.Length; roundKeyIndex++)
  73. {
  74. roundKeys[roundKeyIndex] = new ulong[wordsInBlock];
  75. }
  76. workingKey = new ulong[wordsInKey];
  77. if (keyBytes.Length != wordsInKey * 8)
  78. {
  79. throw new ArgumentException("Invalid key parameter passed to Dstu7624Engine Init");
  80. }
  81. /* Unpack encryption key bytes to words */
  82. Pack.LE_To_UInt64(keyBytes, 0, workingKey);
  83. ulong[] tempKeys = new ulong[wordsInBlock];
  84. /* KSA in DSTU7624 is strengthened to mitigate known weaknesses in AES KSA (eprint.iacr.org/2012/260.pdf) */
  85. WorkingKeyExpandKT(workingKey, tempKeys);
  86. WorkingKeyExpandEven(workingKey, tempKeys);
  87. WorkingKeyExpandOdd();
  88. }
  89. private void WorkingKeyExpandKT(ulong[] workingKey, ulong[] tempKeys)
  90. {
  91. ulong[] k0 = new ulong[wordsInBlock];
  92. ulong[] k1 = new ulong[wordsInBlock];
  93. internalState = new ulong[wordsInBlock];
  94. internalState[0] += (ulong)(wordsInBlock + wordsInKey + 1);
  95. if (wordsInBlock == wordsInKey)
  96. {
  97. Array.Copy(workingKey, 0, k0, 0, k0.Length);
  98. Array.Copy(workingKey, 0, k1, 0, k1.Length);
  99. }
  100. else
  101. {
  102. Array.Copy(workingKey, 0, k0, 0, wordsInBlock);
  103. Array.Copy(workingKey, wordsInBlock, k1, 0, wordsInBlock);
  104. }
  105. for (int wordIndex = 0; wordIndex < internalState.Length; wordIndex++)
  106. {
  107. internalState[wordIndex] += k0[wordIndex];
  108. }
  109. EncryptionRound();
  110. for (int wordIndex = 0; wordIndex < internalState.Length; wordIndex++)
  111. {
  112. internalState[wordIndex] ^= k1[wordIndex];
  113. }
  114. EncryptionRound();
  115. for (int wordIndex = 0; wordIndex < internalState.Length; wordIndex++)
  116. {
  117. internalState[wordIndex] += k0[wordIndex];
  118. }
  119. EncryptionRound();
  120. Array.Copy(internalState, 0, tempKeys, 0, wordsInBlock);
  121. }
  122. private void WorkingKeyExpandEven(ulong[] workingKey, ulong[] tempKey)
  123. {
  124. ulong[] initialData = new ulong[wordsInKey];
  125. ulong[] tempRoundKey = new ulong[wordsInBlock];
  126. int round = 0;
  127. Array.Copy(workingKey, 0, initialData, 0, wordsInKey);
  128. ulong tmv = 0x0001000100010001UL;
  129. while (true)
  130. {
  131. for (int wordIndex = 0; wordIndex < wordsInBlock; wordIndex++)
  132. {
  133. tempRoundKey[wordIndex] = tempKey[wordIndex] + tmv;
  134. }
  135. for (int wordIndex = 0; wordIndex < wordsInBlock; wordIndex++)
  136. {
  137. internalState[wordIndex] = initialData[wordIndex] + tempRoundKey[wordIndex];
  138. }
  139. EncryptionRound();
  140. for (int wordIndex = 0; wordIndex < wordsInBlock; wordIndex++)
  141. {
  142. internalState[wordIndex] ^= tempRoundKey[wordIndex];
  143. }
  144. EncryptionRound();
  145. for (int wordIndex = 0; wordIndex < wordsInBlock; wordIndex++)
  146. {
  147. internalState[wordIndex] += tempRoundKey[wordIndex];
  148. }
  149. Array.Copy(internalState, 0, roundKeys[round], 0, wordsInBlock);
  150. if (roundsAmount == round)
  151. {
  152. break;
  153. }
  154. if (wordsInKey != wordsInBlock)
  155. {
  156. round += 2;
  157. tmv <<= 1;
  158. for (int wordIndex = 0; wordIndex < wordsInBlock; wordIndex++)
  159. {
  160. tempRoundKey[wordIndex] = tempKey[wordIndex] + tmv;
  161. }
  162. for (int wordIndex = 0; wordIndex < wordsInBlock; wordIndex++)
  163. {
  164. internalState[wordIndex] = initialData[wordsInBlock + wordIndex] + tempRoundKey[wordIndex];
  165. }
  166. EncryptionRound();
  167. for (int wordIndex = 0; wordIndex < wordsInBlock; wordIndex++)
  168. {
  169. internalState[wordIndex] ^= tempRoundKey[wordIndex];
  170. }
  171. EncryptionRound();
  172. for (int wordIndex = 0; wordIndex < wordsInBlock; wordIndex++)
  173. {
  174. internalState[wordIndex] += tempRoundKey[wordIndex];
  175. }
  176. Array.Copy(internalState, 0, roundKeys[round], 0, wordsInBlock);
  177. if (roundsAmount == round)
  178. {
  179. break;
  180. }
  181. }
  182. round += 2;
  183. tmv <<= 1;
  184. ulong temp = initialData[0];
  185. for (int i = 1; i < initialData.Length; ++i)
  186. {
  187. initialData[i - 1] = initialData[i];
  188. }
  189. initialData[initialData.Length - 1] = temp;
  190. }
  191. }
  192. private void WorkingKeyExpandOdd()
  193. {
  194. for (int roundIndex = 1; roundIndex < roundsAmount; roundIndex += 2)
  195. {
  196. RotateLeft(roundKeys[roundIndex - 1], roundKeys[roundIndex]);
  197. }
  198. }
  199. #endregion
  200. public virtual int ProcessBlock(byte[] input, int inOff, byte[] output, int outOff)
  201. {
  202. if (workingKey == null)
  203. throw new InvalidOperationException("Dstu7624Engine not initialised");
  204. Check.DataLength(input, inOff, GetBlockSize(), "input buffer too short");
  205. Check.OutputLength(output, outOff, GetBlockSize(), "output buffer too short");
  206. if (forEncryption)
  207. {
  208. /* Encrypt */
  209. switch (wordsInBlock)
  210. {
  211. case 2:
  212. {
  213. EncryptBlock_128(input, inOff, output, outOff);
  214. break;
  215. }
  216. default:
  217. {
  218. Pack.LE_To_UInt64(input, inOff, internalState);
  219. AddRoundKey(0);
  220. for (int round = 0;;)
  221. {
  222. EncryptionRound();
  223. if (++round == roundsAmount)
  224. {
  225. break;
  226. }
  227. XorRoundKey(round);
  228. }
  229. AddRoundKey(roundsAmount);
  230. Pack.UInt64_To_LE(internalState, output, outOff);
  231. break;
  232. }
  233. }
  234. }
  235. else
  236. {
  237. /* Decrypt */
  238. switch (wordsInBlock)
  239. {
  240. case 2:
  241. {
  242. DecryptBlock_128(input, inOff, output, outOff);
  243. break;
  244. }
  245. default:
  246. {
  247. Pack.LE_To_UInt64(input, inOff, internalState);
  248. SubRoundKey(roundsAmount);
  249. for (int round = roundsAmount;;)
  250. {
  251. DecryptionRound();
  252. if (--round == 0)
  253. {
  254. break;
  255. }
  256. XorRoundKey(round);
  257. }
  258. SubRoundKey(0);
  259. Pack.UInt64_To_LE(internalState, output, outOff);
  260. break;
  261. }
  262. }
  263. }
  264. return GetBlockSize();
  265. }
  266. private void EncryptionRound()
  267. {
  268. SubBytes();
  269. ShiftRows();
  270. MixColumns();
  271. }
  272. private void DecryptionRound()
  273. {
  274. MixColumnsInv();
  275. InvShiftRows();
  276. InvSubBytes();
  277. }
  278. private void DecryptBlock_128(byte[] input, int inOff, byte[] output, int outOff)
  279. {
  280. ulong c0 = Pack.LE_To_UInt64(input, inOff);
  281. ulong c1 = Pack.LE_To_UInt64(input, inOff + 8);
  282. ulong[] roundKey = roundKeys[roundsAmount];
  283. c0 -= roundKey[0];
  284. c1 -= roundKey[1];
  285. for (int round = roundsAmount;;)
  286. {
  287. c0 = MixColumnInv(c0);
  288. c1 = MixColumnInv(c1);
  289. uint lo0 = (uint)c0, hi0 = (uint)(c0 >> 32);
  290. uint lo1 = (uint)c1, hi1 = (uint)(c1 >> 32);
  291. {
  292. byte t0 = T0[lo0 & 0xFF];
  293. byte t1 = T1[(lo0 >> 8) & 0xFF];
  294. byte t2 = T2[(lo0 >> 16) & 0xFF];
  295. byte t3 = T3[lo0 >> 24];
  296. lo0 = (uint)t0 | ((uint)t1 << 8) | ((uint)t2 << 16) | ((uint)t3 << 24);
  297. byte t4 = T0[hi1 & 0xFF];
  298. byte t5 = T1[(hi1 >> 8) & 0xFF];
  299. byte t6 = T2[(hi1 >> 16) & 0xFF];
  300. byte t7 = T3[hi1 >> 24];
  301. hi1 = (uint)t4 | ((uint)t5 << 8) | ((uint)t6 << 16) | ((uint)t7 << 24);
  302. c0 = (ulong)lo0 | ((ulong)hi1 << 32);
  303. }
  304. {
  305. byte t0 = T0[lo1 & 0xFF];
  306. byte t1 = T1[(lo1 >> 8) & 0xFF];
  307. byte t2 = T2[(lo1 >> 16) & 0xFF];
  308. byte t3 = T3[lo1 >> 24];
  309. lo1 = (uint)t0 | ((uint)t1 << 8) | ((uint)t2 << 16) | ((uint)t3 << 24);
  310. byte t4 = T0[hi0 & 0xFF];
  311. byte t5 = T1[(hi0 >> 8) & 0xFF];
  312. byte t6 = T2[(hi0 >> 16) & 0xFF];
  313. byte t7 = T3[hi0 >> 24];
  314. hi0 = (uint)t4 | ((uint)t5 << 8) | ((uint)t6 << 16) | ((uint)t7 << 24);
  315. c1 = (ulong)lo1 | ((ulong)hi0 << 32);
  316. }
  317. if (--round == 0)
  318. {
  319. break;
  320. }
  321. roundKey = roundKeys[round];
  322. c0 ^= roundKey[0];
  323. c1 ^= roundKey[1];
  324. }
  325. roundKey = roundKeys[0];
  326. c0 -= roundKey[0];
  327. c1 -= roundKey[1];
  328. Pack.UInt64_To_LE(c0, output, outOff);
  329. Pack.UInt64_To_LE(c1, output, outOff + 8);
  330. }
  331. private void EncryptBlock_128(byte[] input, int inOff, byte[] output, int outOff)
  332. {
  333. ulong c0 = Pack.LE_To_UInt64(input, inOff);
  334. ulong c1 = Pack.LE_To_UInt64(input, inOff + 8);
  335. ulong[] roundKey = roundKeys[0];
  336. c0 += roundKey[0];
  337. c1 += roundKey[1];
  338. for (int round = 0;;)
  339. {
  340. uint lo0 = (uint)c0, hi0 = (uint)(c0 >> 32);
  341. uint lo1 = (uint)c1, hi1 = (uint)(c1 >> 32);
  342. {
  343. byte t0 = S0[lo0 & 0xFF];
  344. byte t1 = S1[(lo0 >> 8) & 0xFF];
  345. byte t2 = S2[(lo0 >> 16) & 0xFF];
  346. byte t3 = S3[lo0 >> 24];
  347. lo0 = (uint)t0 | ((uint)t1 << 8) | ((uint)t2 << 16) | ((uint)t3 << 24);
  348. byte t4 = S0[hi1 & 0xFF];
  349. byte t5 = S1[(hi1 >> 8) & 0xFF];
  350. byte t6 = S2[(hi1 >> 16) & 0xFF];
  351. byte t7 = S3[hi1 >> 24];
  352. hi1 = (uint)t4 | ((uint)t5 << 8) | ((uint)t6 << 16) | ((uint)t7 << 24);
  353. c0 = (ulong)lo0 | ((ulong)hi1 << 32);
  354. }
  355. {
  356. byte t0 = S0[lo1 & 0xFF];
  357. byte t1 = S1[(lo1 >> 8) & 0xFF];
  358. byte t2 = S2[(lo1 >> 16) & 0xFF];
  359. byte t3 = S3[lo1 >> 24];
  360. lo1 = (uint)t0 | ((uint)t1 << 8) | ((uint)t2 << 16) | ((uint)t3 << 24);
  361. byte t4 = S0[hi0 & 0xFF];
  362. byte t5 = S1[(hi0 >> 8) & 0xFF];
  363. byte t6 = S2[(hi0 >> 16) & 0xFF];
  364. byte t7 = S3[hi0 >> 24];
  365. hi0 = (uint)t4 | ((uint)t5 << 8) | ((uint)t6 << 16) | ((uint)t7 << 24);
  366. c1 = (ulong)lo1 | ((ulong)hi0 << 32);
  367. }
  368. c0 = MixColumn(c0);
  369. c1 = MixColumn(c1);
  370. if (++round == roundsAmount)
  371. {
  372. break;
  373. }
  374. roundKey = roundKeys[round];
  375. c0 ^= roundKey[0];
  376. c1 ^= roundKey[1];
  377. }
  378. roundKey = roundKeys[roundsAmount];
  379. c0 += roundKey[0];
  380. c1 += roundKey[1];
  381. Pack.UInt64_To_LE(c0, output, outOff);
  382. Pack.UInt64_To_LE(c1, output, outOff + 8);
  383. }
  384. private void SubBytes()
  385. {
  386. for (int i = 0; i < wordsInBlock; i++)
  387. {
  388. ulong u = internalState[i];
  389. uint lo = (uint)u, hi = (uint)(u >> 32);
  390. byte t0 = S0[lo & 0xFF];
  391. byte t1 = S1[(lo >> 8) & 0xFF];
  392. byte t2 = S2[(lo >> 16) & 0xFF];
  393. byte t3 = S3[lo >> 24];
  394. lo = (uint)t0 | ((uint)t1 << 8) | ((uint)t2 << 16) | ((uint)t3 << 24);
  395. byte t4 = S0[hi & 0xFF];
  396. byte t5 = S1[(hi >> 8) & 0xFF];
  397. byte t6 = S2[(hi >> 16) & 0xFF];
  398. byte t7 = S3[hi >> 24];
  399. hi = (uint)t4 | ((uint)t5 << 8) | ((uint)t6 << 16) | ((uint)t7 << 24);
  400. internalState[i] = (ulong)lo | ((ulong)hi << 32);
  401. }
  402. }
  403. private void InvSubBytes()
  404. {
  405. for (int i = 0; i < wordsInBlock; i++)
  406. {
  407. ulong u = internalState[i];
  408. uint lo = (uint)u, hi = (uint)(u >> 32);
  409. byte t0 = T0[lo & 0xFF];
  410. byte t1 = T1[(lo >> 8) & 0xFF];
  411. byte t2 = T2[(lo >> 16) & 0xFF];
  412. byte t3 = T3[lo >> 24];
  413. lo = (uint)t0 | ((uint)t1 << 8) | ((uint)t2 << 16) | ((uint)t3 << 24);
  414. byte t4 = T0[hi & 0xFF];
  415. byte t5 = T1[(hi >> 8) & 0xFF];
  416. byte t6 = T2[(hi >> 16) & 0xFF];
  417. byte t7 = T3[hi >> 24];
  418. hi = (uint)t4 | ((uint)t5 << 8) | ((uint)t6 << 16) | ((uint)t7 << 24);
  419. internalState[i] = (ulong)lo | ((ulong)hi << 32);
  420. }
  421. }
  422. private void ShiftRows()
  423. {
  424. switch (wordsInBlock)
  425. {
  426. case 2:
  427. {
  428. ulong c0 = internalState[0], c1 = internalState[1];
  429. ulong d;
  430. d = (c0 ^ c1) & 0xFFFFFFFF00000000UL; c0 ^= d; c1 ^= d;
  431. internalState[0] = c0;
  432. internalState[1] = c1;
  433. break;
  434. }
  435. case 4:
  436. {
  437. ulong c0 = internalState[0], c1 = internalState[1], c2 = internalState[2], c3 = internalState[3];
  438. ulong d;
  439. d = (c0 ^ c2) & 0xFFFFFFFF00000000UL; c0 ^= d; c2 ^= d;
  440. d = (c1 ^ c3) & 0x0000FFFFFFFF0000UL; c1 ^= d; c3 ^= d;
  441. d = (c0 ^ c1) & 0xFFFF0000FFFF0000UL; c0 ^= d; c1 ^= d;
  442. d = (c2 ^ c3) & 0xFFFF0000FFFF0000UL; c2 ^= d; c3 ^= d;
  443. internalState[0] = c0;
  444. internalState[1] = c1;
  445. internalState[2] = c2;
  446. internalState[3] = c3;
  447. break;
  448. }
  449. case 8:
  450. {
  451. ulong c0 = internalState[0], c1 = internalState[1], c2 = internalState[2], c3 = internalState[3];
  452. ulong c4 = internalState[4], c5 = internalState[5], c6 = internalState[6], c7 = internalState[7];
  453. ulong d;
  454. d = (c0 ^ c4) & 0xFFFFFFFF00000000UL; c0 ^= d; c4 ^= d;
  455. d = (c1 ^ c5) & 0x00FFFFFFFF000000UL; c1 ^= d; c5 ^= d;
  456. d = (c2 ^ c6) & 0x0000FFFFFFFF0000UL; c2 ^= d; c6 ^= d;
  457. d = (c3 ^ c7) & 0x000000FFFFFFFF00UL; c3 ^= d; c7 ^= d;
  458. d = (c0 ^ c2) & 0xFFFF0000FFFF0000UL; c0 ^= d; c2 ^= d;
  459. d = (c1 ^ c3) & 0x00FFFF0000FFFF00UL; c1 ^= d; c3 ^= d;
  460. d = (c4 ^ c6) & 0xFFFF0000FFFF0000UL; c4 ^= d; c6 ^= d;
  461. d = (c5 ^ c7) & 0x00FFFF0000FFFF00UL; c5 ^= d; c7 ^= d;
  462. d = (c0 ^ c1) & 0xFF00FF00FF00FF00UL; c0 ^= d; c1 ^= d;
  463. d = (c2 ^ c3) & 0xFF00FF00FF00FF00UL; c2 ^= d; c3 ^= d;
  464. d = (c4 ^ c5) & 0xFF00FF00FF00FF00UL; c4 ^= d; c5 ^= d;
  465. d = (c6 ^ c7) & 0xFF00FF00FF00FF00UL; c6 ^= d; c7 ^= d;
  466. internalState[0] = c0;
  467. internalState[1] = c1;
  468. internalState[2] = c2;
  469. internalState[3] = c3;
  470. internalState[4] = c4;
  471. internalState[5] = c5;
  472. internalState[6] = c6;
  473. internalState[7] = c7;
  474. break;
  475. }
  476. default:
  477. {
  478. throw new InvalidOperationException("unsupported block length: only 128/256/512 are allowed");
  479. }
  480. }
  481. }
  482. private void InvShiftRows()
  483. {
  484. switch (wordsInBlock)
  485. {
  486. case 2:
  487. {
  488. ulong c0 = internalState[0], c1 = internalState[1];
  489. ulong d;
  490. d = (c0 ^ c1) & 0xFFFFFFFF00000000UL; c0 ^= d; c1 ^= d;
  491. internalState[0] = c0;
  492. internalState[1] = c1;
  493. break;
  494. }
  495. case 4:
  496. {
  497. ulong c0 = internalState[0], c1 = internalState[1], c2 = internalState[2], c3 = internalState[3];
  498. ulong d;
  499. d = (c0 ^ c1) & 0xFFFF0000FFFF0000UL; c0 ^= d; c1 ^= d;
  500. d = (c2 ^ c3) & 0xFFFF0000FFFF0000UL; c2 ^= d; c3 ^= d;
  501. d = (c0 ^ c2) & 0xFFFFFFFF00000000UL; c0 ^= d; c2 ^= d;
  502. d = (c1 ^ c3) & 0x0000FFFFFFFF0000UL; c1 ^= d; c3 ^= d;
  503. internalState[0] = c0;
  504. internalState[1] = c1;
  505. internalState[2] = c2;
  506. internalState[3] = c3;
  507. break;
  508. }
  509. case 8:
  510. {
  511. ulong c0 = internalState[0], c1 = internalState[1], c2 = internalState[2], c3 = internalState[3];
  512. ulong c4 = internalState[4], c5 = internalState[5], c6 = internalState[6], c7 = internalState[7];
  513. ulong d;
  514. d = (c0 ^ c1) & 0xFF00FF00FF00FF00UL; c0 ^= d; c1 ^= d;
  515. d = (c2 ^ c3) & 0xFF00FF00FF00FF00UL; c2 ^= d; c3 ^= d;
  516. d = (c4 ^ c5) & 0xFF00FF00FF00FF00UL; c4 ^= d; c5 ^= d;
  517. d = (c6 ^ c7) & 0xFF00FF00FF00FF00UL; c6 ^= d; c7 ^= d;
  518. d = (c0 ^ c2) & 0xFFFF0000FFFF0000UL; c0 ^= d; c2 ^= d;
  519. d = (c1 ^ c3) & 0x00FFFF0000FFFF00UL; c1 ^= d; c3 ^= d;
  520. d = (c4 ^ c6) & 0xFFFF0000FFFF0000UL; c4 ^= d; c6 ^= d;
  521. d = (c5 ^ c7) & 0x00FFFF0000FFFF00UL; c5 ^= d; c7 ^= d;
  522. d = (c0 ^ c4) & 0xFFFFFFFF00000000UL; c0 ^= d; c4 ^= d;
  523. d = (c1 ^ c5) & 0x00FFFFFFFF000000UL; c1 ^= d; c5 ^= d;
  524. d = (c2 ^ c6) & 0x0000FFFFFFFF0000UL; c2 ^= d; c6 ^= d;
  525. d = (c3 ^ c7) & 0x000000FFFFFFFF00UL; c3 ^= d; c7 ^= d;
  526. internalState[0] = c0;
  527. internalState[1] = c1;
  528. internalState[2] = c2;
  529. internalState[3] = c3;
  530. internalState[4] = c4;
  531. internalState[5] = c5;
  532. internalState[6] = c6;
  533. internalState[7] = c7;
  534. break;
  535. }
  536. default:
  537. {
  538. throw new InvalidOperationException("unsupported block length: only 128/256/512 are allowed");
  539. }
  540. }
  541. }
  542. private void AddRoundKey(int round)
  543. {
  544. ulong[] roundKey = roundKeys[round];
  545. for (int i = 0; i < wordsInBlock; ++i)
  546. {
  547. internalState[i] += roundKey[i];
  548. }
  549. }
  550. private void SubRoundKey(int round)
  551. {
  552. ulong[] roundKey = roundKeys[round];
  553. for (int i = 0; i < wordsInBlock; ++i)
  554. {
  555. internalState[i] -= roundKey[i];
  556. }
  557. }
  558. private void XorRoundKey(int round)
  559. {
  560. ulong[] roundKey = roundKeys[round];
  561. for (int i = 0; i < wordsInBlock; i++)
  562. {
  563. internalState[i] ^= roundKey[i];
  564. }
  565. }
  566. private static ulong MixColumn(ulong c)
  567. {
  568. //// Calculate column multiplied by powers of 'x'
  569. //ulong x0 = c;
  570. //ulong x1 = MulX(x0);
  571. //ulong x2 = MulX(x1);
  572. //ulong x3 = MulX(x2);
  573. //// Calculate products with circulant matrix from (0x01, 0x01, 0x05, 0x01, 0x08, 0x06, 0x07, 0x04)
  574. //ulong m0 = x0;
  575. //ulong m1 = x0;
  576. //ulong m2 = x0 ^ x2;
  577. //ulong m3 = x0;
  578. //ulong m4 = x3;
  579. //ulong m5 = x1 ^ x2;
  580. //ulong m6 = x0 ^ x1 ^ x2;
  581. //ulong m7 = x2;
  582. //// Assemble the rotated products
  583. //return m0
  584. // ^ Rotate(8, m1)
  585. // ^ Rotate(16, m2)
  586. // ^ Rotate(24, m3)
  587. // ^ Rotate(32, m4)
  588. // ^ Rotate(40, m5)
  589. // ^ Rotate(48, m6)
  590. // ^ Rotate(56, m7);
  591. ulong x1 = MulX(c);
  592. ulong u, v;
  593. u = Rotate(8, c) ^ c;
  594. u ^= Rotate(16, u);
  595. u ^= Rotate(48, c);
  596. v = MulX2(u ^ c ^ x1);
  597. return u ^ Rotate(32, v) ^ Rotate(40, x1) ^ Rotate(48, x1);
  598. }
  599. private void MixColumns()
  600. {
  601. for (int col = 0; col < wordsInBlock; ++col)
  602. {
  603. internalState[col] = MixColumn(internalState[col]);
  604. }
  605. }
  606. private static ulong MixColumnInv(ulong c)
  607. {
  608. /*
  609. // Calculate column multiplied by powers of 'x'
  610. ulong x0 = c;
  611. ulong x1 = MulX(x0);
  612. ulong x2 = MulX(x1);
  613. ulong x3 = MulX(x2);
  614. ulong x4 = MulX(x3);
  615. ulong x5 = MulX(x4);
  616. ulong x6 = MulX(x5);
  617. ulong x7 = MulX(x6);
  618. // Calculate products with circulant matrix from (0xAD,0x95,0x76,0xA8,0x2F,0x49,0xD7,0xCA)
  619. //long m0 = x0 ^ x2 ^ x3 ^ x5 ^ x7;
  620. //long m1 = x0 ^ x2 ^ x4 ^ x7;
  621. //long m2 = x1 ^ x2 ^ x4 ^ x5 ^ x6;
  622. //long m3 = x3 ^ x5 ^ x7;
  623. //long m4 = x0 ^ x1 ^ x2 ^ x3 ^ x5;
  624. //long m5 = x0 ^ x3 ^ x6;
  625. //long m6 = x0 ^ x1 ^ x2 ^ x4 ^ x6 ^ x7;
  626. //long m7 = x1 ^ x3 ^ x6 ^ x7;
  627. ulong m5 = x0 ^ x3 ^ x6;
  628. x0 ^= x2;
  629. ulong m3 = x3 ^ x5 ^ x7;
  630. ulong m0 = m3 ^ x0;
  631. ulong m6 = x0 ^ x4;
  632. ulong m1 = m6 ^ x7;
  633. x5 ^= x1;
  634. x7 ^= x1 ^ x6;
  635. ulong m2 = x2 ^ x4 ^ x5 ^ x6;
  636. ulong m4 = x0 ^ x3 ^ x5;
  637. m6 ^= x7;
  638. ulong m7 = x3 ^ x7;
  639. // Assemble the rotated products
  640. return m0
  641. ^ Rotate(8, m1)
  642. ^ Rotate(16, m2)
  643. ^ Rotate(24, m3)
  644. ^ Rotate(32, m4)
  645. ^ Rotate(40, m5)
  646. ^ Rotate(48, m6)
  647. ^ Rotate(56, m7);
  648. */
  649. ulong u0 = c;
  650. u0 ^= Rotate( 8, u0);
  651. u0 ^= Rotate(32, u0);
  652. u0 ^= Rotate(48, c);
  653. ulong t = u0 ^ c;
  654. ulong c48 = Rotate(48, c);
  655. ulong c56 = Rotate(56, c);
  656. ulong u7 = t ^ c56;
  657. ulong u6 = Rotate(56, t);
  658. u6 ^= MulX(u7);
  659. ulong u5 = Rotate(16, t) ^ c;
  660. u5 ^= Rotate(40, MulX(u6) ^ c);
  661. ulong u4 = t ^ c48;
  662. u4 ^= MulX(u5);
  663. ulong u3 = Rotate(16, u0);
  664. u3 ^= MulX(u4);
  665. ulong u2 = t ^ Rotate(24, c) ^ c48 ^ c56;
  666. u2 ^= MulX(u3);
  667. ulong u1 = Rotate(32, t) ^ c ^ c56;
  668. u1 ^= MulX(u2);
  669. u0 ^= MulX(Rotate(40, u1));
  670. return u0;
  671. }
  672. private void MixColumnsInv()
  673. {
  674. for (int col = 0; col < wordsInBlock; ++col)
  675. {
  676. internalState[col] = MixColumnInv(internalState[col]);
  677. }
  678. }
  679. private static ulong MulX(ulong n)
  680. {
  681. return ((n & 0x7F7F7F7F7F7F7F7FUL) << 1) ^ (((n & 0x8080808080808080UL) >> 7) * 0x1DUL);
  682. }
  683. private static ulong MulX2(ulong n)
  684. {
  685. return ((n & 0x3F3F3F3F3F3F3F3FUL) << 2) ^ (((n & 0x8080808080808080UL) >> 6) * 0x1DUL) ^ (((n & 0x4040404040404040UL) >> 6) * 0x1DUL);
  686. }
  687. //private static ulong MulX4(ulong n)
  688. //{
  689. // ulong u = n & 0xF0F0F0F0F0F0F0F0UL;
  690. // return ((n & 0x0F0F0F0F0F0F0F0FUL) << 4) ^ u ^ (u >> 1) ^ (u >> 2) ^ (u >> 4);
  691. //}
  692. /*
  693. * Pair-wise modular multiplication of 8 byte-pairs.
  694. *
  695. * REDUCTION_POLYNOMIAL is x^8 + x^4 + x^3 + x^2 + 1
  696. */
  697. //private static ulong MultiplyGFx8(ulong u, ulong v, int vMaxDegree)
  698. //{
  699. // ulong r = u & ((v & 0x0101010101010101UL) * 0xFFUL);
  700. // for (int i = 1; i <= vMaxDegree; ++i)
  701. // {
  702. // u = ((u & 0x7F7F7F7F7F7F7F7FUL) << 1) ^ (((u >> 7) & 0x0101010101010101UL) * 0x1DUL);
  703. // v >>= 1;
  704. // r ^= u & ((v & 0x0101010101010101UL) * 0xFFUL);
  705. // }
  706. // return r;
  707. //}
  708. //private static ulong MultiplyMds(ulong u)
  709. //{
  710. // ulong r = 0, s = 0, t = (u >> 8);
  711. // r ^= u & 0x0000001F00000000UL; r <<= 1;
  712. // s ^= t & 0x00000000E0000000UL; s <<= 1;
  713. // r ^= u & 0x3F3F3F00003F0000UL; r <<= 1;
  714. // s ^= t & 0x00C0C0C00000C000UL; s <<= 1;
  715. // r ^= u & 0x007F7F0000000000UL; r <<= 1;
  716. // s ^= t & 0x0000808000000000UL; s <<= 1;
  717. // r ^= u & 0x00FF0000FFFFFFFFUL;
  718. // r ^= s ^ (s << 2) ^ (s << 3) ^ (s << 4);
  719. // return r;
  720. //}
  721. private static ulong Rotate(int n, ulong x)
  722. {
  723. return (x >> n) | (x << -n);
  724. }
  725. private void RotateLeft(ulong[] x, ulong[] z)
  726. {
  727. switch (wordsInBlock)
  728. {
  729. case 2:
  730. {
  731. ulong x0 = x[0], x1 = x[1];
  732. z[0] = (x0 >> 56) | (x1 << 8);
  733. z[1] = (x1 >> 56) | (x0 << 8);
  734. break;
  735. }
  736. case 4:
  737. {
  738. ulong x0 = x[0], x1 = x[1], x2 = x[2], x3 = x[3];
  739. z[0] = (x1 >> 24) | (x2 << 40);
  740. z[1] = (x2 >> 24) | (x3 << 40);
  741. z[2] = (x3 >> 24) | (x0 << 40);
  742. z[3] = (x0 >> 24) | (x1 << 40);
  743. break;
  744. }
  745. case 8:
  746. {
  747. ulong x0 = x[0], x1 = x[1], x2 = x[2], x3 = x[3];
  748. ulong x4 = x[4], x5 = x[5], x6 = x[6], x7 = x[7];
  749. z[0] = (x2 >> 24) | (x3 << 40);
  750. z[1] = (x3 >> 24) | (x4 << 40);
  751. z[2] = (x4 >> 24) | (x5 << 40);
  752. z[3] = (x5 >> 24) | (x6 << 40);
  753. z[4] = (x6 >> 24) | (x7 << 40);
  754. z[5] = (x7 >> 24) | (x0 << 40);
  755. z[6] = (x0 >> 24) | (x1 << 40);
  756. z[7] = (x1 >> 24) | (x2 << 40);
  757. break;
  758. }
  759. default:
  760. {
  761. throw new InvalidOperationException("unsupported block length: only 128/256/512 are allowed");
  762. }
  763. }
  764. }
  765. #region TABLES AND S-BOXES
  766. private const ulong mdsMatrix = 0x0407060801050101UL;
  767. private const ulong mdsInvMatrix = 0xCAD7492FA87695ADUL;
  768. private static readonly byte[] S0 = new byte[]{
  769. 0xa8, 0x43, 0x5f, 0x06, 0x6b, 0x75, 0x6c, 0x59, 0x71, 0xdf, 0x87, 0x95, 0x17, 0xf0, 0xd8, 0x09,
  770. 0x6d, 0xf3, 0x1d, 0xcb, 0xc9, 0x4d, 0x2c, 0xaf, 0x79, 0xe0, 0x97, 0xfd, 0x6f, 0x4b, 0x45, 0x39,
  771. 0x3e, 0xdd, 0xa3, 0x4f, 0xb4, 0xb6, 0x9a, 0x0e, 0x1f, 0xbf, 0x15, 0xe1, 0x49, 0xd2, 0x93, 0xc6,
  772. 0x92, 0x72, 0x9e, 0x61, 0xd1, 0x63, 0xfa, 0xee, 0xf4, 0x19, 0xd5, 0xad, 0x58, 0xa4, 0xbb, 0xa1,
  773. 0xdc, 0xf2, 0x83, 0x37, 0x42, 0xe4, 0x7a, 0x32, 0x9c, 0xcc, 0xab, 0x4a, 0x8f, 0x6e, 0x04, 0x27,
  774. 0x2e, 0xe7, 0xe2, 0x5a, 0x96, 0x16, 0x23, 0x2b, 0xc2, 0x65, 0x66, 0x0f, 0xbc, 0xa9, 0x47, 0x41,
  775. 0x34, 0x48, 0xfc, 0xb7, 0x6a, 0x88, 0xa5, 0x53, 0x86, 0xf9, 0x5b, 0xdb, 0x38, 0x7b, 0xc3, 0x1e,
  776. 0x22, 0x33, 0x24, 0x28, 0x36, 0xc7, 0xb2, 0x3b, 0x8e, 0x77, 0xba, 0xf5, 0x14, 0x9f, 0x08, 0x55,
  777. 0x9b, 0x4c, 0xfe, 0x60, 0x5c, 0xda, 0x18, 0x46, 0xcd, 0x7d, 0x21, 0xb0, 0x3f, 0x1b, 0x89, 0xff,
  778. 0xeb, 0x84, 0x69, 0x3a, 0x9d, 0xd7, 0xd3, 0x70, 0x67, 0x40, 0xb5, 0xde, 0x5d, 0x30, 0x91, 0xb1,
  779. 0x78, 0x11, 0x01, 0xe5, 0x00, 0x68, 0x98, 0xa0, 0xc5, 0x02, 0xa6, 0x74, 0x2d, 0x0b, 0xa2, 0x76,
  780. 0xb3, 0xbe, 0xce, 0xbd, 0xae, 0xe9, 0x8a, 0x31, 0x1c, 0xec, 0xf1, 0x99, 0x94, 0xaa, 0xf6, 0x26,
  781. 0x2f, 0xef, 0xe8, 0x8c, 0x35, 0x03, 0xd4, 0x7f, 0xfb, 0x05, 0xc1, 0x5e, 0x90, 0x20, 0x3d, 0x82,
  782. 0xf7, 0xea, 0x0a, 0x0d, 0x7e, 0xf8, 0x50, 0x1a, 0xc4, 0x07, 0x57, 0xb8, 0x3c, 0x62, 0xe3, 0xc8,
  783. 0xac, 0x52, 0x64, 0x10, 0xd0, 0xd9, 0x13, 0x0c, 0x12, 0x29, 0x51, 0xb9, 0xcf, 0xd6, 0x73, 0x8d,
  784. 0x81, 0x54, 0xc0, 0xed, 0x4e, 0x44, 0xa7, 0x2a, 0x85, 0x25, 0xe6, 0xca, 0x7c, 0x8b, 0x56, 0x80
  785. };
  786. private static readonly byte[] S1 = new byte[]{
  787. 0xce, 0xbb, 0xeb, 0x92, 0xea, 0xcb, 0x13, 0xc1, 0xe9, 0x3a, 0xd6, 0xb2, 0xd2, 0x90, 0x17, 0xf8,
  788. 0x42, 0x15, 0x56, 0xb4, 0x65, 0x1c, 0x88, 0x43, 0xc5, 0x5c, 0x36, 0xba, 0xf5, 0x57, 0x67, 0x8d,
  789. 0x31, 0xf6, 0x64, 0x58, 0x9e, 0xf4, 0x22, 0xaa, 0x75, 0x0f, 0x02, 0xb1, 0xdf, 0x6d, 0x73, 0x4d,
  790. 0x7c, 0x26, 0x2e, 0xf7, 0x08, 0x5d, 0x44, 0x3e, 0x9f, 0x14, 0xc8, 0xae, 0x54, 0x10, 0xd8, 0xbc,
  791. 0x1a, 0x6b, 0x69, 0xf3, 0xbd, 0x33, 0xab, 0xfa, 0xd1, 0x9b, 0x68, 0x4e, 0x16, 0x95, 0x91, 0xee,
  792. 0x4c, 0x63, 0x8e, 0x5b, 0xcc, 0x3c, 0x19, 0xa1, 0x81, 0x49, 0x7b, 0xd9, 0x6f, 0x37, 0x60, 0xca,
  793. 0xe7, 0x2b, 0x48, 0xfd, 0x96, 0x45, 0xfc, 0x41, 0x12, 0x0d, 0x79, 0xe5, 0x89, 0x8c, 0xe3, 0x20,
  794. 0x30, 0xdc, 0xb7, 0x6c, 0x4a, 0xb5, 0x3f, 0x97, 0xd4, 0x62, 0x2d, 0x06, 0xa4, 0xa5, 0x83, 0x5f,
  795. 0x2a, 0xda, 0xc9, 0x00, 0x7e, 0xa2, 0x55, 0xbf, 0x11, 0xd5, 0x9c, 0xcf, 0x0e, 0x0a, 0x3d, 0x51,
  796. 0x7d, 0x93, 0x1b, 0xfe, 0xc4, 0x47, 0x09, 0x86, 0x0b, 0x8f, 0x9d, 0x6a, 0x07, 0xb9, 0xb0, 0x98,
  797. 0x18, 0x32, 0x71, 0x4b, 0xef, 0x3b, 0x70, 0xa0, 0xe4, 0x40, 0xff, 0xc3, 0xa9, 0xe6, 0x78, 0xf9,
  798. 0x8b, 0x46, 0x80, 0x1e, 0x38, 0xe1, 0xb8, 0xa8, 0xe0, 0x0c, 0x23, 0x76, 0x1d, 0x25, 0x24, 0x05,
  799. 0xf1, 0x6e, 0x94, 0x28, 0x9a, 0x84, 0xe8, 0xa3, 0x4f, 0x77, 0xd3, 0x85, 0xe2, 0x52, 0xf2, 0x82,
  800. 0x50, 0x7a, 0x2f, 0x74, 0x53, 0xb3, 0x61, 0xaf, 0x39, 0x35, 0xde, 0xcd, 0x1f, 0x99, 0xac, 0xad,
  801. 0x72, 0x2c, 0xdd, 0xd0, 0x87, 0xbe, 0x5e, 0xa6, 0xec, 0x04, 0xc6, 0x03, 0x34, 0xfb, 0xdb, 0x59,
  802. 0xb6, 0xc2, 0x01, 0xf0, 0x5a, 0xed, 0xa7, 0x66, 0x21, 0x7f, 0x8a, 0x27, 0xc7, 0xc0, 0x29, 0xd7
  803. };
  804. private static readonly byte[] S2 = new byte[]{
  805. 0x93, 0xd9, 0x9a, 0xb5, 0x98, 0x22, 0x45, 0xfc, 0xba, 0x6a, 0xdf, 0x02, 0x9f, 0xdc, 0x51, 0x59,
  806. 0x4a, 0x17, 0x2b, 0xc2, 0x94, 0xf4, 0xbb, 0xa3, 0x62, 0xe4, 0x71, 0xd4, 0xcd, 0x70, 0x16, 0xe1,
  807. 0x49, 0x3c, 0xc0, 0xd8, 0x5c, 0x9b, 0xad, 0x85, 0x53, 0xa1, 0x7a, 0xc8, 0x2d, 0xe0, 0xd1, 0x72,
  808. 0xa6, 0x2c, 0xc4, 0xe3, 0x76, 0x78, 0xb7, 0xb4, 0x09, 0x3b, 0x0e, 0x41, 0x4c, 0xde, 0xb2, 0x90,
  809. 0x25, 0xa5, 0xd7, 0x03, 0x11, 0x00, 0xc3, 0x2e, 0x92, 0xef, 0x4e, 0x12, 0x9d, 0x7d, 0xcb, 0x35,
  810. 0x10, 0xd5, 0x4f, 0x9e, 0x4d, 0xa9, 0x55, 0xc6, 0xd0, 0x7b, 0x18, 0x97, 0xd3, 0x36, 0xe6, 0x48,
  811. 0x56, 0x81, 0x8f, 0x77, 0xcc, 0x9c, 0xb9, 0xe2, 0xac, 0xb8, 0x2f, 0x15, 0xa4, 0x7c, 0xda, 0x38,
  812. 0x1e, 0x0b, 0x05, 0xd6, 0x14, 0x6e, 0x6c, 0x7e, 0x66, 0xfd, 0xb1, 0xe5, 0x60, 0xaf, 0x5e, 0x33,
  813. 0x87, 0xc9, 0xf0, 0x5d, 0x6d, 0x3f, 0x88, 0x8d, 0xc7, 0xf7, 0x1d, 0xe9, 0xec, 0xed, 0x80, 0x29,
  814. 0x27, 0xcf, 0x99, 0xa8, 0x50, 0x0f, 0x37, 0x24, 0x28, 0x30, 0x95, 0xd2, 0x3e, 0x5b, 0x40, 0x83,
  815. 0xb3, 0x69, 0x57, 0x1f, 0x07, 0x1c, 0x8a, 0xbc, 0x20, 0xeb, 0xce, 0x8e, 0xab, 0xee, 0x31, 0xa2,
  816. 0x73, 0xf9, 0xca, 0x3a, 0x1a, 0xfb, 0x0d, 0xc1, 0xfe, 0xfa, 0xf2, 0x6f, 0xbd, 0x96, 0xdd, 0x43,
  817. 0x52, 0xb6, 0x08, 0xf3, 0xae, 0xbe, 0x19, 0x89, 0x32, 0x26, 0xb0, 0xea, 0x4b, 0x64, 0x84, 0x82,
  818. 0x6b, 0xf5, 0x79, 0xbf, 0x01, 0x5f, 0x75, 0x63, 0x1b, 0x23, 0x3d, 0x68, 0x2a, 0x65, 0xe8, 0x91,
  819. 0xf6, 0xff, 0x13, 0x58, 0xf1, 0x47, 0x0a, 0x7f, 0xc5, 0xa7, 0xe7, 0x61, 0x5a, 0x06, 0x46, 0x44,
  820. 0x42, 0x04, 0xa0, 0xdb, 0x39, 0x86, 0x54, 0xaa, 0x8c, 0x34, 0x21, 0x8b, 0xf8, 0x0c, 0x74, 0x67
  821. };
  822. private static readonly byte[] S3 = new byte[]{
  823. 0x68, 0x8d, 0xca, 0x4d, 0x73, 0x4b, 0x4e, 0x2a, 0xd4, 0x52, 0x26, 0xb3, 0x54, 0x1e, 0x19, 0x1f,
  824. 0x22, 0x03, 0x46, 0x3d, 0x2d, 0x4a, 0x53, 0x83, 0x13, 0x8a, 0xb7, 0xd5, 0x25, 0x79, 0xf5, 0xbd,
  825. 0x58, 0x2f, 0x0d, 0x02, 0xed, 0x51, 0x9e, 0x11, 0xf2, 0x3e, 0x55, 0x5e, 0xd1, 0x16, 0x3c, 0x66,
  826. 0x70, 0x5d, 0xf3, 0x45, 0x40, 0xcc, 0xe8, 0x94, 0x56, 0x08, 0xce, 0x1a, 0x3a, 0xd2, 0xe1, 0xdf,
  827. 0xb5, 0x38, 0x6e, 0x0e, 0xe5, 0xf4, 0xf9, 0x86, 0xe9, 0x4f, 0xd6, 0x85, 0x23, 0xcf, 0x32, 0x99,
  828. 0x31, 0x14, 0xae, 0xee, 0xc8, 0x48, 0xd3, 0x30, 0xa1, 0x92, 0x41, 0xb1, 0x18, 0xc4, 0x2c, 0x71,
  829. 0x72, 0x44, 0x15, 0xfd, 0x37, 0xbe, 0x5f, 0xaa, 0x9b, 0x88, 0xd8, 0xab, 0x89, 0x9c, 0xfa, 0x60,
  830. 0xea, 0xbc, 0x62, 0x0c, 0x24, 0xa6, 0xa8, 0xec, 0x67, 0x20, 0xdb, 0x7c, 0x28, 0xdd, 0xac, 0x5b,
  831. 0x34, 0x7e, 0x10, 0xf1, 0x7b, 0x8f, 0x63, 0xa0, 0x05, 0x9a, 0x43, 0x77, 0x21, 0xbf, 0x27, 0x09,
  832. 0xc3, 0x9f, 0xb6, 0xd7, 0x29, 0xc2, 0xeb, 0xc0, 0xa4, 0x8b, 0x8c, 0x1d, 0xfb, 0xff, 0xc1, 0xb2,
  833. 0x97, 0x2e, 0xf8, 0x65, 0xf6, 0x75, 0x07, 0x04, 0x49, 0x33, 0xe4, 0xd9, 0xb9, 0xd0, 0x42, 0xc7,
  834. 0x6c, 0x90, 0x00, 0x8e, 0x6f, 0x50, 0x01, 0xc5, 0xda, 0x47, 0x3f, 0xcd, 0x69, 0xa2, 0xe2, 0x7a,
  835. 0xa7, 0xc6, 0x93, 0x0f, 0x0a, 0x06, 0xe6, 0x2b, 0x96, 0xa3, 0x1c, 0xaf, 0x6a, 0x12, 0x84, 0x39,
  836. 0xe7, 0xb0, 0x82, 0xf7, 0xfe, 0x9d, 0x87, 0x5c, 0x81, 0x35, 0xde, 0xb4, 0xa5, 0xfc, 0x80, 0xef,
  837. 0xcb, 0xbb, 0x6b, 0x76, 0xba, 0x5a, 0x7d, 0x78, 0x0b, 0x95, 0xe3, 0xad, 0x74, 0x98, 0x3b, 0x36,
  838. 0x64, 0x6d, 0xdc, 0xf0, 0x59, 0xa9, 0x4c, 0x17, 0x7f, 0x91, 0xb8, 0xc9, 0x57, 0x1b, 0xe0, 0x61
  839. };
  840. private static readonly byte[] T0 = new byte[]{
  841. 0xa4, 0xa2, 0xa9, 0xc5, 0x4e, 0xc9, 0x03, 0xd9, 0x7e, 0x0f, 0xd2, 0xad, 0xe7, 0xd3, 0x27, 0x5b,
  842. 0xe3, 0xa1, 0xe8, 0xe6, 0x7c, 0x2a, 0x55, 0x0c, 0x86, 0x39, 0xd7, 0x8d, 0xb8, 0x12, 0x6f, 0x28,
  843. 0xcd, 0x8a, 0x70, 0x56, 0x72, 0xf9, 0xbf, 0x4f, 0x73, 0xe9, 0xf7, 0x57, 0x16, 0xac, 0x50, 0xc0,
  844. 0x9d, 0xb7, 0x47, 0x71, 0x60, 0xc4, 0x74, 0x43, 0x6c, 0x1f, 0x93, 0x77, 0xdc, 0xce, 0x20, 0x8c,
  845. 0x99, 0x5f, 0x44, 0x01, 0xf5, 0x1e, 0x87, 0x5e, 0x61, 0x2c, 0x4b, 0x1d, 0x81, 0x15, 0xf4, 0x23,
  846. 0xd6, 0xea, 0xe1, 0x67, 0xf1, 0x7f, 0xfe, 0xda, 0x3c, 0x07, 0x53, 0x6a, 0x84, 0x9c, 0xcb, 0x02,
  847. 0x83, 0x33, 0xdd, 0x35, 0xe2, 0x59, 0x5a, 0x98, 0xa5, 0x92, 0x64, 0x04, 0x06, 0x10, 0x4d, 0x1c,
  848. 0x97, 0x08, 0x31, 0xee, 0xab, 0x05, 0xaf, 0x79, 0xa0, 0x18, 0x46, 0x6d, 0xfc, 0x89, 0xd4, 0xc7,
  849. 0xff, 0xf0, 0xcf, 0x42, 0x91, 0xf8, 0x68, 0x0a, 0x65, 0x8e, 0xb6, 0xfd, 0xc3, 0xef, 0x78, 0x4c,
  850. 0xcc, 0x9e, 0x30, 0x2e, 0xbc, 0x0b, 0x54, 0x1a, 0xa6, 0xbb, 0x26, 0x80, 0x48, 0x94, 0x32, 0x7d,
  851. 0xa7, 0x3f, 0xae, 0x22, 0x3d, 0x66, 0xaa, 0xf6, 0x00, 0x5d, 0xbd, 0x4a, 0xe0, 0x3b, 0xb4, 0x17,
  852. 0x8b, 0x9f, 0x76, 0xb0, 0x24, 0x9a, 0x25, 0x63, 0xdb, 0xeb, 0x7a, 0x3e, 0x5c, 0xb3, 0xb1, 0x29,
  853. 0xf2, 0xca, 0x58, 0x6e, 0xd8, 0xa8, 0x2f, 0x75, 0xdf, 0x14, 0xfb, 0x13, 0x49, 0x88, 0xb2, 0xec,
  854. 0xe4, 0x34, 0x2d, 0x96, 0xc6, 0x3a, 0xed, 0x95, 0x0e, 0xe5, 0x85, 0x6b, 0x40, 0x21, 0x9b, 0x09,
  855. 0x19, 0x2b, 0x52, 0xde, 0x45, 0xa3, 0xfa, 0x51, 0xc2, 0xb5, 0xd1, 0x90, 0xb9, 0xf3, 0x37, 0xc1,
  856. 0x0d, 0xba, 0x41, 0x11, 0x38, 0x7b, 0xbe, 0xd0, 0xd5, 0x69, 0x36, 0xc8, 0x62, 0x1b, 0x82, 0x8f
  857. };
  858. private static readonly byte[] T1 = new byte[]{
  859. 0x83, 0xf2, 0x2a, 0xeb, 0xe9, 0xbf, 0x7b, 0x9c, 0x34, 0x96, 0x8d, 0x98, 0xb9, 0x69, 0x8c, 0x29,
  860. 0x3d, 0x88, 0x68, 0x06, 0x39, 0x11, 0x4c, 0x0e, 0xa0, 0x56, 0x40, 0x92, 0x15, 0xbc, 0xb3, 0xdc,
  861. 0x6f, 0xf8, 0x26, 0xba, 0xbe, 0xbd, 0x31, 0xfb, 0xc3, 0xfe, 0x80, 0x61, 0xe1, 0x7a, 0x32, 0xd2,
  862. 0x70, 0x20, 0xa1, 0x45, 0xec, 0xd9, 0x1a, 0x5d, 0xb4, 0xd8, 0x09, 0xa5, 0x55, 0x8e, 0x37, 0x76,
  863. 0xa9, 0x67, 0x10, 0x17, 0x36, 0x65, 0xb1, 0x95, 0x62, 0x59, 0x74, 0xa3, 0x50, 0x2f, 0x4b, 0xc8,
  864. 0xd0, 0x8f, 0xcd, 0xd4, 0x3c, 0x86, 0x12, 0x1d, 0x23, 0xef, 0xf4, 0x53, 0x19, 0x35, 0xe6, 0x7f,
  865. 0x5e, 0xd6, 0x79, 0x51, 0x22, 0x14, 0xf7, 0x1e, 0x4a, 0x42, 0x9b, 0x41, 0x73, 0x2d, 0xc1, 0x5c,
  866. 0xa6, 0xa2, 0xe0, 0x2e, 0xd3, 0x28, 0xbb, 0xc9, 0xae, 0x6a, 0xd1, 0x5a, 0x30, 0x90, 0x84, 0xf9,
  867. 0xb2, 0x58, 0xcf, 0x7e, 0xc5, 0xcb, 0x97, 0xe4, 0x16, 0x6c, 0xfa, 0xb0, 0x6d, 0x1f, 0x52, 0x99,
  868. 0x0d, 0x4e, 0x03, 0x91, 0xc2, 0x4d, 0x64, 0x77, 0x9f, 0xdd, 0xc4, 0x49, 0x8a, 0x9a, 0x24, 0x38,
  869. 0xa7, 0x57, 0x85, 0xc7, 0x7c, 0x7d, 0xe7, 0xf6, 0xb7, 0xac, 0x27, 0x46, 0xde, 0xdf, 0x3b, 0xd7,
  870. 0x9e, 0x2b, 0x0b, 0xd5, 0x13, 0x75, 0xf0, 0x72, 0xb6, 0x9d, 0x1b, 0x01, 0x3f, 0x44, 0xe5, 0x87,
  871. 0xfd, 0x07, 0xf1, 0xab, 0x94, 0x18, 0xea, 0xfc, 0x3a, 0x82, 0x5f, 0x05, 0x54, 0xdb, 0x00, 0x8b,
  872. 0xe3, 0x48, 0x0c, 0xca, 0x78, 0x89, 0x0a, 0xff, 0x3e, 0x5b, 0x81, 0xee, 0x71, 0xe2, 0xda, 0x2c,
  873. 0xb8, 0xb5, 0xcc, 0x6e, 0xa8, 0x6b, 0xad, 0x60, 0xc6, 0x08, 0x04, 0x02, 0xe8, 0xf5, 0x4f, 0xa4,
  874. 0xf3, 0xc0, 0xce, 0x43, 0x25, 0x1c, 0x21, 0x33, 0x0f, 0xaf, 0x47, 0xed, 0x66, 0x63, 0x93, 0xaa
  875. };
  876. private static readonly byte[] T2 = new byte[]{
  877. 0x45, 0xd4, 0x0b, 0x43, 0xf1, 0x72, 0xed, 0xa4, 0xc2, 0x38, 0xe6, 0x71, 0xfd, 0xb6, 0x3a, 0x95,
  878. 0x50, 0x44, 0x4b, 0xe2, 0x74, 0x6b, 0x1e, 0x11, 0x5a, 0xc6, 0xb4, 0xd8, 0xa5, 0x8a, 0x70, 0xa3,
  879. 0xa8, 0xfa, 0x05, 0xd9, 0x97, 0x40, 0xc9, 0x90, 0x98, 0x8f, 0xdc, 0x12, 0x31, 0x2c, 0x47, 0x6a,
  880. 0x99, 0xae, 0xc8, 0x7f, 0xf9, 0x4f, 0x5d, 0x96, 0x6f, 0xf4, 0xb3, 0x39, 0x21, 0xda, 0x9c, 0x85,
  881. 0x9e, 0x3b, 0xf0, 0xbf, 0xef, 0x06, 0xee, 0xe5, 0x5f, 0x20, 0x10, 0xcc, 0x3c, 0x54, 0x4a, 0x52,
  882. 0x94, 0x0e, 0xc0, 0x28, 0xf6, 0x56, 0x60, 0xa2, 0xe3, 0x0f, 0xec, 0x9d, 0x24, 0x83, 0x7e, 0xd5,
  883. 0x7c, 0xeb, 0x18, 0xd7, 0xcd, 0xdd, 0x78, 0xff, 0xdb, 0xa1, 0x09, 0xd0, 0x76, 0x84, 0x75, 0xbb,
  884. 0x1d, 0x1a, 0x2f, 0xb0, 0xfe, 0xd6, 0x34, 0x63, 0x35, 0xd2, 0x2a, 0x59, 0x6d, 0x4d, 0x77, 0xe7,
  885. 0x8e, 0x61, 0xcf, 0x9f, 0xce, 0x27, 0xf5, 0x80, 0x86, 0xc7, 0xa6, 0xfb, 0xf8, 0x87, 0xab, 0x62,
  886. 0x3f, 0xdf, 0x48, 0x00, 0x14, 0x9a, 0xbd, 0x5b, 0x04, 0x92, 0x02, 0x25, 0x65, 0x4c, 0x53, 0x0c,
  887. 0xf2, 0x29, 0xaf, 0x17, 0x6c, 0x41, 0x30, 0xe9, 0x93, 0x55, 0xf7, 0xac, 0x68, 0x26, 0xc4, 0x7d,
  888. 0xca, 0x7a, 0x3e, 0xa0, 0x37, 0x03, 0xc1, 0x36, 0x69, 0x66, 0x08, 0x16, 0xa7, 0xbc, 0xc5, 0xd3,
  889. 0x22, 0xb7, 0x13, 0x46, 0x32, 0xe8, 0x57, 0x88, 0x2b, 0x81, 0xb2, 0x4e, 0x64, 0x1c, 0xaa, 0x91,
  890. 0x58, 0x2e, 0x9b, 0x5c, 0x1b, 0x51, 0x73, 0x42, 0x23, 0x01, 0x6e, 0xf3, 0x0d, 0xbe, 0x3d, 0x0a,
  891. 0x2d, 0x1f, 0x67, 0x33, 0x19, 0x7b, 0x5e, 0xea, 0xde, 0x8b, 0xcb, 0xa9, 0x8c, 0x8d, 0xad, 0x49,
  892. 0x82, 0xe4, 0xba, 0xc3, 0x15, 0xd1, 0xe0, 0x89, 0xfc, 0xb1, 0xb9, 0xb5, 0x07, 0x79, 0xb8, 0xe1
  893. };
  894. private static readonly byte[] T3 = new byte[]{
  895. 0xb2, 0xb6, 0x23, 0x11, 0xa7, 0x88, 0xc5, 0xa6, 0x39, 0x8f, 0xc4, 0xe8, 0x73, 0x22, 0x43, 0xc3,
  896. 0x82, 0x27, 0xcd, 0x18, 0x51, 0x62, 0x2d, 0xf7, 0x5c, 0x0e, 0x3b, 0xfd, 0xca, 0x9b, 0x0d, 0x0f,
  897. 0x79, 0x8c, 0x10, 0x4c, 0x74, 0x1c, 0x0a, 0x8e, 0x7c, 0x94, 0x07, 0xc7, 0x5e, 0x14, 0xa1, 0x21,
  898. 0x57, 0x50, 0x4e, 0xa9, 0x80, 0xd9, 0xef, 0x64, 0x41, 0xcf, 0x3c, 0xee, 0x2e, 0x13, 0x29, 0xba,
  899. 0x34, 0x5a, 0xae, 0x8a, 0x61, 0x33, 0x12, 0xb9, 0x55, 0xa8, 0x15, 0x05, 0xf6, 0x03, 0x06, 0x49,
  900. 0xb5, 0x25, 0x09, 0x16, 0x0c, 0x2a, 0x38, 0xfc, 0x20, 0xf4, 0xe5, 0x7f, 0xd7, 0x31, 0x2b, 0x66,
  901. 0x6f, 0xff, 0x72, 0x86, 0xf0, 0xa3, 0x2f, 0x78, 0x00, 0xbc, 0xcc, 0xe2, 0xb0, 0xf1, 0x42, 0xb4,
  902. 0x30, 0x5f, 0x60, 0x04, 0xec, 0xa5, 0xe3, 0x8b, 0xe7, 0x1d, 0xbf, 0x84, 0x7b, 0xe6, 0x81, 0xf8,
  903. 0xde, 0xd8, 0xd2, 0x17, 0xce, 0x4b, 0x47, 0xd6, 0x69, 0x6c, 0x19, 0x99, 0x9a, 0x01, 0xb3, 0x85,
  904. 0xb1, 0xf9, 0x59, 0xc2, 0x37, 0xe9, 0xc8, 0xa0, 0xed, 0x4f, 0x89, 0x68, 0x6d, 0xd5, 0x26, 0x91,
  905. 0x87, 0x58, 0xbd, 0xc9, 0x98, 0xdc, 0x75, 0xc0, 0x76, 0xf5, 0x67, 0x6b, 0x7e, 0xeb, 0x52, 0xcb,
  906. 0xd1, 0x5b, 0x9f, 0x0b, 0xdb, 0x40, 0x92, 0x1a, 0xfa, 0xac, 0xe4, 0xe1, 0x71, 0x1f, 0x65, 0x8d,
  907. 0x97, 0x9e, 0x95, 0x90, 0x5d, 0xb7, 0xc1, 0xaf, 0x54, 0xfb, 0x02, 0xe0, 0x35, 0xbb, 0x3a, 0x4d,
  908. 0xad, 0x2c, 0x3d, 0x56, 0x08, 0x1b, 0x4a, 0x93, 0x6a, 0xab, 0xb8, 0x7a, 0xf2, 0x7d, 0xda, 0x3f,
  909. 0xfe, 0x3e, 0xbe, 0xea, 0xaa, 0x44, 0xc6, 0xd0, 0x36, 0x48, 0x70, 0x96, 0x77, 0x24, 0x53, 0xdf,
  910. 0xf3, 0x83, 0x28, 0x32, 0x45, 0x1e, 0xa4, 0xd3, 0xa2, 0x46, 0x6e, 0x9c, 0xdd, 0x63, 0xd4, 0x9d
  911. };
  912. #endregion
  913. public virtual string AlgorithmName
  914. {
  915. get { return "DSTU7624"; }
  916. }
  917. public virtual int GetBlockSize()
  918. {
  919. return wordsInBlock << 3;
  920. }
  921. public virtual bool IsPartialBlockOkay
  922. {
  923. get { return false; }
  924. }
  925. public virtual void Reset()
  926. {
  927. Array.Clear(internalState, 0, internalState.Length);
  928. }
  929. }
  930. }
  931. #pragma warning restore
  932. #endif