AesEngine
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Crypto.Utilities;
using Org.BouncyCastle.Utilities;
using System;
namespace Org.BouncyCastle.Crypto.Engines
{
public sealed class AesEngine : IBlockCipher
{
private static readonly byte[] S = new byte[256] {
99,
124,
119,
123,
242,
107,
111,
197,
48,
1,
103,
43,
254,
215,
171,
118,
202,
130,
201,
125,
250,
89,
71,
240,
173,
212,
162,
175,
156,
164,
114,
192,
183,
253,
147,
38,
54,
63,
247,
204,
52,
165,
229,
241,
113,
216,
49,
21,
4,
199,
35,
195,
24,
150,
5,
154,
7,
18,
128,
226,
235,
39,
178,
117,
9,
131,
44,
26,
27,
110,
90,
160,
82,
59,
214,
179,
41,
227,
47,
132,
83,
209,
0,
237,
32,
252,
177,
91,
106,
203,
190,
57,
74,
76,
88,
207,
208,
239,
170,
251,
67,
77,
51,
133,
69,
249,
2,
127,
80,
60,
159,
168,
81,
163,
64,
143,
146,
157,
56,
245,
188,
182,
218,
33,
16,
byte.MaxValue,
243,
210,
205,
12,
19,
236,
95,
151,
68,
23,
196,
167,
126,
61,
100,
93,
25,
115,
96,
129,
79,
220,
34,
42,
144,
136,
70,
238,
184,
20,
222,
94,
11,
219,
224,
50,
58,
10,
73,
6,
36,
92,
194,
211,
172,
98,
145,
149,
228,
121,
231,
200,
55,
109,
141,
213,
78,
169,
108,
86,
244,
234,
101,
122,
174,
8,
186,
120,
37,
46,
28,
166,
180,
198,
232,
221,
116,
31,
75,
189,
139,
138,
112,
62,
181,
102,
72,
3,
246,
14,
97,
53,
87,
185,
134,
193,
29,
158,
225,
248,
152,
17,
105,
217,
142,
148,
155,
30,
135,
233,
206,
85,
40,
223,
140,
161,
137,
13,
191,
230,
66,
104,
65,
153,
45,
15,
176,
84,
187,
22
};
private static readonly byte[] Si = new byte[256] {
82,
9,
106,
213,
48,
54,
165,
56,
191,
64,
163,
158,
129,
243,
215,
251,
124,
227,
57,
130,
155,
47,
byte.MaxValue,
135,
52,
142,
67,
68,
196,
222,
233,
203,
84,
123,
148,
50,
166,
194,
35,
61,
238,
76,
149,
11,
66,
250,
195,
78,
8,
46,
161,
102,
40,
217,
36,
178,
118,
91,
162,
73,
109,
139,
209,
37,
114,
248,
246,
100,
134,
104,
152,
22,
212,
164,
92,
204,
93,
101,
182,
146,
108,
112,
72,
80,
253,
237,
185,
218,
94,
21,
70,
87,
167,
141,
157,
132,
144,
216,
171,
0,
140,
188,
211,
10,
247,
228,
88,
5,
184,
179,
69,
6,
208,
44,
30,
143,
202,
63,
15,
2,
193,
175,
189,
3,
1,
19,
138,
107,
58,
145,
17,
65,
79,
103,
220,
234,
151,
242,
207,
206,
240,
180,
230,
115,
150,
172,
116,
34,
231,
173,
53,
133,
226,
249,
55,
232,
28,
117,
223,
110,
71,
241,
26,
113,
29,
41,
197,
137,
111,
183,
98,
14,
170,
24,
190,
27,
252,
86,
62,
75,
198,
210,
121,
32,
154,
219,
192,
254,
120,
205,
90,
244,
31,
221,
168,
51,
136,
7,
199,
49,
177,
18,
16,
89,
39,
128,
236,
95,
96,
81,
127,
169,
25,
181,
74,
13,
45,
229,
122,
159,
147,
201,
156,
239,
160,
224,
59,
77,
174,
42,
245,
176,
200,
235,
187,
60,
131,
83,
153,
97,
23,
43,
4,
126,
186,
119,
214,
38,
225,
105,
20,
99,
85,
33,
12,
125
};
private static readonly byte[] rcon = new byte[30] {
1,
2,
4,
8,
16,
32,
64,
128,
27,
54,
108,
216,
171,
77,
154,
47,
94,
188,
99,
198,
151,
53,
106,
212,
179,
125,
250,
239,
197,
145
};
private static readonly uint[] T0 = new uint[256] {
2774754246,
2222750968,
2574743534,
2373680118,
234025727,
3177933782,
2976870366,
1422247313,
1345335392,
50397442,
2842126286,
2099981142,
436141799,
1658312629,
3870010189,
2591454956,
1170918031,
2642575903,
1086966153,
2273148410,
368769775,
3948501426,
3376891790,
200339707,
3970805057,
1742001331,
4255294047,
3937382213,
3214711843,
4154762323,
2524082916,
1539358875,
3266819957,
486407649,
2928907069,
1780885068,
1513502316,
1094664062,
49805301,
1338821763,
1546925160,
4104496465,
887481809,
150073849,
2473685474,
1943591083,
1395732834,
1058346282,
201589768,
1388824469,
1696801606,
1589887901,
672667696,
2711000631,
251987210,
3046808111,
151455502,
907153956,
2608889883,
1038279391,
652995533,
1764173646,
3451040383,
2675275242,
453576978,
2659418909,
1949051992,
773462580,
756751158,
2993581788,
3998898868,
4221608027,
4132590244,
1295727478,
1641469623,
3467883389,
2066295122,
1055122397,
1898917726,
2542044179,
4115878822,
1758581177,
0,
753790401,
1612718144,
536673507,
3367088505,
3982187446,
3194645204,
1187761037,
3653156455,
1262041458,
3729410708,
3561770136,
3898103984,
1255133061,
1808847035,
720367557,
3853167183,
385612781,
3309519750,
3612167578,
1429418854,
2491778321,
3477423498,
284817897,
100794884,
2172616702,
4031795360,
1144798328,
3131023141,
3819481163,
4082192802,
4272137053,
3225436288,
2324664069,
2912064063,
3164445985,
1211644016,
83228145,
3753688163,
3249976951,
1977277103,
1663115586,
806359072,
452984805,
250868733,
1842533055,
1288555905,
336333848,
890442534,
804056259,
3781124030,
2727843637,
3427026056,
957814574,
1472513171,
4071073621,
2189328124,
1195195770,
2892260552,
3881655738,
723065138,
2507371494,
2690670784,
2558624025,
3511635870,
2145180835,
1713513028,
2116692564,
2878378043,
2206763019,
3393603212,
703524551,
3552098411,
1007948840,
2044649127,
3797835452,
487262998,
1994120109,
1004593371,
1446130276,
1312438900,
503974420,
3679013266,
168166924,
1814307912,
3831258296,
1573044895,
1859376061,
4021070915,
2791465668,
2828112185,
2761266481,
937747667,
2339994098,
854058965,
1137232011,
1496790894,
3077402074,
2358086913,
1691735473,
3528347292,
3769215305,
3027004632,
4199962284,
133494003,
636152527,
2942657994,
2390391540,
3920539207,
403179536,
3585784431,
2289596656,
1864705354,
1915629148,
605822008,
4054230615,
3350508659,
1371981463,
602466507,
2094914977,
2624877800,
555687742,
3712699286,
3703422305,
2257292045,
2240449039,
2423288032,
1111375484,
3300242801,
2858837708,
3628615824,
84083462,
32962295,
302911004,
2741068226,
1597322602,
4183250862,
3501832553,
2441512471,
1489093017,
656219450,
3114180135,
954327513,
335083755,
3013122091,
856756514,
3144247762,
1893325225,
2307821063,
2811532339,
3063651117,
572399164,
2458355477,
552200649,
1238290055,
4283782570,
2015897680,
2061492133,
2408352771,
4171342169,
2156497161,
386731290,
3669999461,
837215959,
3326231172,
3093850320,
3275833730,
2962856233,
1999449434,
286199582,
3417354363,
4233385128,
3602627437,
974525996
};
private static readonly uint[] Tinv0 = new uint[256] {
1353184337,
1399144830,
3282310938,
2522752826,
3412831035,
4047871263,
2874735276,
2466505547,
1442459680,
4134368941,
2440481928,
625738485,
4242007375,
3620416197,
2151953702,
2409849525,
1230680542,
1729870373,
2551114309,
3787521629,
41234371,
317738113,
2744600205,
3338261355,
3881799427,
2510066197,
3950669247,
3663286933,
763608788,
3542185048,
694804553,
1154009486,
1787413109,
2021232372,
1799248025,
3715217703,
3058688446,
397248752,
1722556617,
3023752829,
407560035,
2184256229,
1613975959,
1165972322,
3765920945,
2226023355,
480281086,
2485848313,
1483229296,
436028815,
2272059028,
3086515026,
601060267,
3791801202,
1468997603,
715871590,
120122290,
63092015,
2591802758,
2768779219,
4068943920,
2997206819,
3127509762,
1552029421,
723308426,
2461301159,
4042393587,
2715969870,
3455375973,
3586000134,
526529745,
2331944644,
2639474228,
2689987490,
853641733,
1978398372,
971801355,
2867814464,
111112542,
1360031421,
4186579262,
1023860118,
2919579357,
1186850381,
3045938321,
90031217,
1876166148,
4279586912,
620468249,
2548678102,
3426959497,
2006899047,
3175278768,
2290845959,
945494503,
3689859193,
1191869601,
3910091388,
3374220536,
0,
2206629897,
1223502642,
2893025566,
1316117100,
4227796733,
1446544655,
517320253,
658058550,
1691946762,
564550760,
3511966619,
976107044,
2976320012,
266819475,
3533106868,
2660342555,
1338359936,
2720062561,
1766553434,
370807324,
179999714,
3844776128,
1138762300,
488053522,
185403662,
2915535858,
3114841645,
3366526484,
2233069911,
1275557295,
3151862254,
4250959779,
2670068215,
3170202204,
3309004356,
880737115,
1982415755,
3703972811,
1761406390,
1676797112,
3403428311,
277177154,
1076008723,
538035844,
2099530373,
4164795346,
288553390,
1839278535,
1261411869,
4080055004,
3964831245,
3504587127,
1813426987,
2579067049,
4199060497,
577038663,
3297574056,
440397984,
3626794326,
4019204898,
3343796615,
3251714265,
4272081548,
906744984,
3481400742,
685669029,
646887386,
2764025151,
3835509292,
227702864,
2613862250,
1648787028,
3256061430,
3904428176,
1593260334,
4121936770,
3196083615,
2090061929,
2838353263,
3004310991,
999926984,
2809993232,
1852021992,
2075868123,
158869197,
4095236462,
28809964,
2828685187,
1701746150,
2129067946,
147831841,
3873969647,
3650873274,
3459673930,
3557400554,
3598495785,
2947720241,
824393514,
815048134,
3227951669,
935087732,
2798289660,
2966458592,
366520115,
1251476721,
4158319681,
240176511,
804688151,
2379631990,
1303441219,
1414376140,
3741619940,
3820343710,
461924940,
3089050817,
2136040774,
82468509,
1563790337,
1937016826,
776014843,
1511876531,
1389550482,
861278441,
323475053,
2355222426,
2047648055,
2383738969,
2302415851,
3995576782,
902390199,
3991215329,
1018251130,
1507840668,
1064563285,
2043548696,
3208103795,
3939366739,
1537932639,
342834655,
2262516856,
2180231114,
1053059257,
741614648,
1598071746,
1925389590,
203809468,
2336832552,
1100287487,
1895934009,
3736275976,
2632234200,
2428589668,
1636092795,
1890988757,
1952214088,
1113045200
};
private const uint m1 = 2155905152;
private const uint m2 = 2139062143;
private const uint m3 = 27;
private const uint m4 = 3233857728;
private const uint m5 = 1061109567;
private int ROUNDS;
private uint[][] WorkingKey;
private bool forEncryption;
private byte[] s;
private const int BLOCK_SIZE = 16;
public string AlgorithmName => "AES";
private static uint Shift(uint r, int shift)
{
return (r >> shift) | (r << 32 - shift);
}
private static uint FFmulX(uint x)
{
return ((x & 2139062143) << 1) ^ (((uint)((int)x & -2139062144) >> 7) * 27);
}
private static uint FFmulX2(uint x)
{
uint num = (x & 1061109567) << 2;
uint num2 = (uint)((int)x & -1061109568);
num2 ^= num2 >> 1;
return num ^ (num2 >> 2) ^ (num2 >> 5);
}
private static uint Inv_Mcol(uint x)
{
uint num = x ^ Shift(x, 8);
uint num2 = x ^ FFmulX(num);
num ^= FFmulX2(num2);
return num2 ^ (num ^ Shift(num, 16));
}
private static uint SubWord(uint x)
{
return (uint)(S[x & 255] | (S[(x >> 8) & 255] << 8) | (S[(x >> 16) & 255] << 16) | (S[(x >> 24) & 255] << 24));
}
private uint[][] GenerateWorkingKey(KeyParameter keyParameter, bool forEncryption)
{
byte[] key = keyParameter.GetKey();
int num = key.Length;
if (num < 16 || num > 32 || (num & 7) != 0)
throw new ArgumentException("Key length not 128/192/256 bits.");
int num2 = num >> 2;
ROUNDS = num2 + 6;
uint[][] array = new uint[ROUNDS + 1][];
for (int i = 0; i <= ROUNDS; i++) {
array[i] = new uint[4];
}
switch (num2) {
case 4: {
uint num21 = Pack.LE_To_UInt32(key, 0);
array[0][0] = num21;
uint num22 = Pack.LE_To_UInt32(key, 4);
array[0][1] = num22;
uint num23 = Pack.LE_To_UInt32(key, 8);
array[0][2] = num23;
uint num24 = Pack.LE_To_UInt32(key, 12);
array[0][3] = num24;
for (int l = 1; l <= 10; l++) {
uint num25 = SubWord(Shift(num24, 8)) ^ rcon[l - 1];
num21 ^= num25;
array[l][0] = num21;
num22 ^= num21;
array[l][1] = num22;
num23 ^= num22;
array[l][2] = num23;
num24 ^= num23;
array[l][3] = num24;
}
break;
}
case 6: {
uint num13 = Pack.LE_To_UInt32(key, 0);
array[0][0] = num13;
uint num14 = Pack.LE_To_UInt32(key, 4);
array[0][1] = num14;
uint num15 = Pack.LE_To_UInt32(key, 8);
array[0][2] = num15;
uint num16 = Pack.LE_To_UInt32(key, 12);
array[0][3] = num16;
uint num17 = Pack.LE_To_UInt32(key, 16);
array[1][0] = num17;
uint num18 = Pack.LE_To_UInt32(key, 20);
array[1][1] = num18;
uint num19 = 1;
uint num20 = SubWord(Shift(num18, 8)) ^ num19;
num19 <<= 1;
num13 ^= num20;
array[1][2] = num13;
num14 ^= num13;
array[1][3] = num14;
num15 ^= num14;
array[2][0] = num15;
num16 ^= num15;
array[2][1] = num16;
num17 ^= num16;
array[2][2] = num17;
num18 ^= num17;
array[2][3] = num18;
for (int k = 3; k < 12; k += 3) {
num20 = (SubWord(Shift(num18, 8)) ^ num19);
num19 <<= 1;
num13 ^= num20;
array[k][0] = num13;
num14 ^= num13;
array[k][1] = num14;
num15 ^= num14;
array[k][2] = num15;
num16 ^= num15;
array[k][3] = num16;
num17 ^= num16;
array[k + 1][0] = num17;
num18 ^= num17;
array[k + 1][1] = num18;
num20 = (SubWord(Shift(num18, 8)) ^ num19);
num19 <<= 1;
num13 ^= num20;
array[k + 1][2] = num13;
num14 ^= num13;
array[k + 1][3] = num14;
num15 ^= num14;
array[k + 2][0] = num15;
num16 ^= num15;
array[k + 2][1] = num16;
num17 ^= num16;
array[k + 2][2] = num17;
num18 ^= num17;
array[k + 2][3] = num18;
}
num20 = (SubWord(Shift(num18, 8)) ^ num19);
num13 ^= num20;
array[12][0] = num13;
num14 ^= num13;
array[12][1] = num14;
num15 ^= num14;
array[12][2] = num15;
num16 ^= num15;
array[12][3] = num16;
break;
}
case 8: {
uint num3 = Pack.LE_To_UInt32(key, 0);
array[0][0] = num3;
uint num4 = Pack.LE_To_UInt32(key, 4);
array[0][1] = num4;
uint num5 = Pack.LE_To_UInt32(key, 8);
array[0][2] = num5;
uint num6 = Pack.LE_To_UInt32(key, 12);
array[0][3] = num6;
uint num7 = Pack.LE_To_UInt32(key, 16);
array[1][0] = num7;
uint num8 = Pack.LE_To_UInt32(key, 20);
array[1][1] = num8;
uint num9 = Pack.LE_To_UInt32(key, 24);
array[1][2] = num9;
uint num10 = Pack.LE_To_UInt32(key, 28);
array[1][3] = num10;
uint num11 = 1;
uint num12;
for (int j = 2; j < 14; j += 2) {
num12 = (SubWord(Shift(num10, 8)) ^ num11);
num11 <<= 1;
num3 ^= num12;
array[j][0] = num3;
num4 ^= num3;
array[j][1] = num4;
num5 ^= num4;
array[j][2] = num5;
num6 ^= num5;
array[j][3] = num6;
num12 = SubWord(num6);
num7 ^= num12;
array[j + 1][0] = num7;
num8 ^= num7;
array[j + 1][1] = num8;
num9 ^= num8;
array[j + 1][2] = num9;
num10 ^= num9;
array[j + 1][3] = num10;
}
num12 = (SubWord(Shift(num10, 8)) ^ num11);
num3 ^= num12;
array[14][0] = num3;
num4 ^= num3;
array[14][1] = num4;
num5 ^= num4;
array[14][2] = num5;
num6 ^= num5;
array[14][3] = num6;
break;
}
default:
throw new InvalidOperationException("Should never get here");
}
if (!forEncryption) {
for (int m = 1; m < ROUNDS; m++) {
uint[] array2 = array[m];
for (int n = 0; n < 4; n++) {
array2[n] = Inv_Mcol(array2[n]);
}
}
}
return array;
}
public void Init(bool forEncryption, ICipherParameters parameters)
{
KeyParameter keyParameter = parameters as KeyParameter;
if (keyParameter == null)
throw new ArgumentException("invalid parameter passed to AES init - " + Platform.GetTypeName(parameters));
WorkingKey = GenerateWorkingKey(keyParameter, forEncryption);
this.forEncryption = forEncryption;
s = Arrays.Clone(forEncryption ? S : Si);
}
public int GetBlockSize()
{
return 16;
}
public int ProcessBlock(byte[] input, int inOff, byte[] output, int outOff)
{
if (WorkingKey == null)
throw new InvalidOperationException("AES engine not initialised");
Check.DataLength(input, inOff, 16, "input buffer too short");
Check.OutputLength(output, outOff, 16, "output buffer too short");
if (forEncryption)
EncryptBlock(input, inOff, output, outOff, WorkingKey);
else
DecryptBlock(input, inOff, output, outOff, WorkingKey);
return 16;
}
private void EncryptBlock(byte[] input, int inOff, byte[] output, int outOff, uint[][] KW)
{
uint num = Pack.LE_To_UInt32(input, inOff);
uint num2 = Pack.LE_To_UInt32(input, inOff + 4);
uint num3 = Pack.LE_To_UInt32(input, inOff + 8);
uint num4 = Pack.LE_To_UInt32(input, inOff + 12);
uint[] array = KW[0];
uint num5 = num ^ array[0];
uint num6 = num2 ^ array[1];
uint num7 = num3 ^ array[2];
uint num8 = num4 ^ array[3];
int num9 = 1;
uint num11;
uint num12;
uint num13;
while (num9 < ROUNDS - 1) {
array = KW[num9++];
num11 = (T0[num5 & 255] ^ Shift(T0[(num6 >> 8) & 255], 24) ^ Shift(T0[(num7 >> 16) & 255], 16) ^ Shift(T0[(num8 >> 24) & 255], 8) ^ array[0]);
num12 = (T0[num6 & 255] ^ Shift(T0[(num7 >> 8) & 255], 24) ^ Shift(T0[(num8 >> 16) & 255], 16) ^ Shift(T0[(num5 >> 24) & 255], 8) ^ array[1]);
num13 = (T0[num7 & 255] ^ Shift(T0[(num8 >> 8) & 255], 24) ^ Shift(T0[(num5 >> 16) & 255], 16) ^ Shift(T0[(num6 >> 24) & 255], 8) ^ array[2]);
num8 = (T0[num8 & 255] ^ Shift(T0[(num5 >> 8) & 255], 24) ^ Shift(T0[(num6 >> 16) & 255], 16) ^ Shift(T0[(num7 >> 24) & 255], 8) ^ array[3]);
array = KW[num9++];
num5 = (T0[num11 & 255] ^ Shift(T0[(num12 >> 8) & 255], 24) ^ Shift(T0[(num13 >> 16) & 255], 16) ^ Shift(T0[(num8 >> 24) & 255], 8) ^ array[0]);
num6 = (T0[num12 & 255] ^ Shift(T0[(num13 >> 8) & 255], 24) ^ Shift(T0[(num8 >> 16) & 255], 16) ^ Shift(T0[(num11 >> 24) & 255], 8) ^ array[1]);
num7 = (T0[num13 & 255] ^ Shift(T0[(num8 >> 8) & 255], 24) ^ Shift(T0[(num11 >> 16) & 255], 16) ^ Shift(T0[(num12 >> 24) & 255], 8) ^ array[2]);
num8 = (T0[num8 & 255] ^ Shift(T0[(num11 >> 8) & 255], 24) ^ Shift(T0[(num12 >> 16) & 255], 16) ^ Shift(T0[(num13 >> 24) & 255], 8) ^ array[3]);
}
array = KW[num9++];
num11 = (T0[num5 & 255] ^ Shift(T0[(num6 >> 8) & 255], 24) ^ Shift(T0[(num7 >> 16) & 255], 16) ^ Shift(T0[(num8 >> 24) & 255], 8) ^ array[0]);
num12 = (T0[num6 & 255] ^ Shift(T0[(num7 >> 8) & 255], 24) ^ Shift(T0[(num8 >> 16) & 255], 16) ^ Shift(T0[(num5 >> 24) & 255], 8) ^ array[1]);
num13 = (T0[num7 & 255] ^ Shift(T0[(num8 >> 8) & 255], 24) ^ Shift(T0[(num5 >> 16) & 255], 16) ^ Shift(T0[(num6 >> 24) & 255], 8) ^ array[2]);
num8 = (T0[num8 & 255] ^ Shift(T0[(num5 >> 8) & 255], 24) ^ Shift(T0[(num6 >> 16) & 255], 16) ^ Shift(T0[(num7 >> 24) & 255], 8) ^ array[3]);
array = KW[num9];
num = (uint)(S[num11 & 255] ^ (S[(num12 >> 8) & 255] << 8) ^ (s[(num13 >> 16) & 255] << 16) ^ (s[(num8 >> 24) & 255] << 24) ^ (int)array[0]);
num2 = (uint)(s[num12 & 255] ^ (S[(num13 >> 8) & 255] << 8) ^ (S[(num8 >> 16) & 255] << 16) ^ (s[(num11 >> 24) & 255] << 24) ^ (int)array[1]);
num3 = (uint)(s[num13 & 255] ^ (S[(num8 >> 8) & 255] << 8) ^ (S[(num11 >> 16) & 255] << 16) ^ (S[(num12 >> 24) & 255] << 24) ^ (int)array[2]);
int n = s[num8 & 255] ^ (s[(num11 >> 8) & 255] << 8) ^ (s[(num12 >> 16) & 255] << 16) ^ (S[(num13 >> 24) & 255] << 24) ^ (int)array[3];
Pack.UInt32_To_LE(num, output, outOff);
Pack.UInt32_To_LE(num2, output, outOff + 4);
Pack.UInt32_To_LE(num3, output, outOff + 8);
Pack.UInt32_To_LE((uint)n, output, outOff + 12);
}
private void DecryptBlock(byte[] input, int inOff, byte[] output, int outOff, uint[][] KW)
{
uint num = Pack.LE_To_UInt32(input, inOff);
uint num2 = Pack.LE_To_UInt32(input, inOff + 4);
uint num3 = Pack.LE_To_UInt32(input, inOff + 8);
uint num4 = Pack.LE_To_UInt32(input, inOff + 12);
uint[] array = KW[ROUNDS];
uint num5 = num ^ array[0];
uint num6 = num2 ^ array[1];
uint num7 = num3 ^ array[2];
uint num8 = num4 ^ array[3];
int num9 = ROUNDS - 1;
uint num11;
uint num12;
uint num13;
while (num9 > 1) {
array = KW[num9--];
num11 = (Tinv0[num5 & 255] ^ Shift(Tinv0[(num8 >> 8) & 255], 24) ^ Shift(Tinv0[(num7 >> 16) & 255], 16) ^ Shift(Tinv0[(num6 >> 24) & 255], 8) ^ array[0]);
num12 = (Tinv0[num6 & 255] ^ Shift(Tinv0[(num5 >> 8) & 255], 24) ^ Shift(Tinv0[(num8 >> 16) & 255], 16) ^ Shift(Tinv0[(num7 >> 24) & 255], 8) ^ array[1]);
num13 = (Tinv0[num7 & 255] ^ Shift(Tinv0[(num6 >> 8) & 255], 24) ^ Shift(Tinv0[(num5 >> 16) & 255], 16) ^ Shift(Tinv0[(num8 >> 24) & 255], 8) ^ array[2]);
num8 = (Tinv0[num8 & 255] ^ Shift(Tinv0[(num7 >> 8) & 255], 24) ^ Shift(Tinv0[(num6 >> 16) & 255], 16) ^ Shift(Tinv0[(num5 >> 24) & 255], 8) ^ array[3]);
array = KW[num9--];
num5 = (Tinv0[num11 & 255] ^ Shift(Tinv0[(num8 >> 8) & 255], 24) ^ Shift(Tinv0[(num13 >> 16) & 255], 16) ^ Shift(Tinv0[(num12 >> 24) & 255], 8) ^ array[0]);
num6 = (Tinv0[num12 & 255] ^ Shift(Tinv0[(num11 >> 8) & 255], 24) ^ Shift(Tinv0[(num8 >> 16) & 255], 16) ^ Shift(Tinv0[(num13 >> 24) & 255], 8) ^ array[1]);
num7 = (Tinv0[num13 & 255] ^ Shift(Tinv0[(num12 >> 8) & 255], 24) ^ Shift(Tinv0[(num11 >> 16) & 255], 16) ^ Shift(Tinv0[(num8 >> 24) & 255], 8) ^ array[2]);
num8 = (Tinv0[num8 & 255] ^ Shift(Tinv0[(num13 >> 8) & 255], 24) ^ Shift(Tinv0[(num12 >> 16) & 255], 16) ^ Shift(Tinv0[(num11 >> 24) & 255], 8) ^ array[3]);
}
array = KW[1];
num11 = (Tinv0[num5 & 255] ^ Shift(Tinv0[(num8 >> 8) & 255], 24) ^ Shift(Tinv0[(num7 >> 16) & 255], 16) ^ Shift(Tinv0[(num6 >> 24) & 255], 8) ^ array[0]);
num12 = (Tinv0[num6 & 255] ^ Shift(Tinv0[(num5 >> 8) & 255], 24) ^ Shift(Tinv0[(num8 >> 16) & 255], 16) ^ Shift(Tinv0[(num7 >> 24) & 255], 8) ^ array[1]);
num13 = (Tinv0[num7 & 255] ^ Shift(Tinv0[(num6 >> 8) & 255], 24) ^ Shift(Tinv0[(num5 >> 16) & 255], 16) ^ Shift(Tinv0[(num8 >> 24) & 255], 8) ^ array[2]);
num8 = (Tinv0[num8 & 255] ^ Shift(Tinv0[(num7 >> 8) & 255], 24) ^ Shift(Tinv0[(num6 >> 16) & 255], 16) ^ Shift(Tinv0[(num5 >> 24) & 255], 8) ^ array[3]);
array = KW[0];
num = (uint)(Si[num11 & 255] ^ (s[(num8 >> 8) & 255] << 8) ^ (s[(num13 >> 16) & 255] << 16) ^ (Si[(num12 >> 24) & 255] << 24) ^ (int)array[0]);
num2 = (uint)(s[num12 & 255] ^ (s[(num11 >> 8) & 255] << 8) ^ (Si[(num8 >> 16) & 255] << 16) ^ (s[(num13 >> 24) & 255] << 24) ^ (int)array[1]);
num3 = (uint)(s[num13 & 255] ^ (Si[(num12 >> 8) & 255] << 8) ^ (Si[(num11 >> 16) & 255] << 16) ^ (s[(num8 >> 24) & 255] << 24) ^ (int)array[2]);
int n = Si[num8 & 255] ^ (s[(num13 >> 8) & 255] << 8) ^ (s[(num12 >> 16) & 255] << 16) ^ (s[(num11 >> 24) & 255] << 24) ^ (int)array[3];
Pack.UInt32_To_LE(num, output, outOff);
Pack.UInt32_To_LE(num2, output, outOff + 4);
Pack.UInt32_To_LE(num3, output, outOff + 8);
Pack.UInt32_To_LE((uint)n, output, outOff + 12);
}
}
}