AriaEngine
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.Utilities.Encoders;
using System;
namespace Org.BouncyCastle.Crypto.Engines
{
public class AriaEngine : IBlockCipher
{
private static readonly byte[][] C = new byte[3][] {
Hex.DecodeStrict("517cc1b727220a94fe13abe8fa9a6ee0"),
Hex.DecodeStrict("6db14acc9e21c820ff28b1d5ef5de2b0"),
Hex.DecodeStrict("db92371d2126e9700324977504e8c90e")
};
private static readonly byte[] SB1_sbox = 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[] SB2_sbox = new byte[256] {
226,
78,
84,
252,
148,
194,
74,
204,
98,
13,
106,
70,
60,
77,
139,
209,
94,
250,
100,
203,
180,
151,
190,
43,
188,
119,
46,
3,
211,
25,
89,
193,
29,
6,
65,
107,
85,
240,
153,
105,
234,
156,
24,
174,
99,
223,
231,
187,
0,
115,
102,
251,
150,
76,
133,
228,
58,
9,
69,
170,
15,
238,
16,
235,
45,
127,
244,
41,
172,
207,
173,
145,
141,
120,
200,
149,
249,
47,
206,
205,
8,
122,
136,
56,
92,
131,
42,
40,
71,
219,
184,
199,
147,
164,
18,
83,
byte.MaxValue,
135,
14,
49,
54,
33,
88,
72,
1,
142,
55,
116,
50,
202,
233,
177,
183,
171,
12,
215,
196,
86,
66,
38,
7,
152,
96,
217,
182,
185,
17,
64,
236,
32,
140,
189,
160,
201,
132,
4,
73,
35,
241,
79,
80,
31,
19,
220,
216,
192,
158,
87,
227,
195,
123,
101,
59,
2,
143,
62,
232,
37,
146,
229,
21,
221,
253,
23,
169,
191,
212,
154,
126,
197,
57,
103,
254,
118,
157,
67,
167,
225,
208,
245,
104,
242,
27,
52,
112,
5,
163,
138,
213,
121,
134,
168,
48,
198,
81,
75,
30,
166,
39,
246,
53,
210,
110,
36,
22,
130,
95,
218,
230,
117,
162,
239,
44,
178,
28,
159,
93,
111,
128,
10,
114,
68,
155,
108,
144,
11,
91,
51,
125,
90,
82,
243,
97,
161,
247,
176,
214,
63,
124,
109,
237,
20,
224,
165,
61,
34,
179,
248,
137,
222,
113,
26,
175,
186,
181,
129
};
private static readonly byte[] SB3_sbox = 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[] SB4_sbox = new byte[256] {
48,
104,
153,
27,
135,
185,
33,
120,
80,
57,
219,
225,
114,
9,
98,
60,
62,
126,
94,
142,
241,
160,
204,
163,
42,
29,
251,
182,
214,
32,
196,
141,
129,
101,
245,
137,
203,
157,
119,
198,
87,
67,
86,
23,
212,
64,
26,
77,
192,
99,
108,
227,
183,
200,
100,
106,
83,
170,
56,
152,
12,
244,
155,
237,
127,
34,
118,
175,
221,
58,
11,
88,
103,
136,
6,
195,
53,
13,
1,
139,
140,
194,
230,
95,
2,
36,
117,
147,
102,
30,
229,
226,
84,
216,
16,
206,
122,
232,
8,
44,
18,
151,
50,
171,
180,
39,
10,
35,
223,
239,
202,
217,
184,
250,
220,
49,
107,
209,
173,
25,
73,
189,
81,
150,
238,
228,
168,
65,
218,
byte.MaxValue,
205,
85,
134,
54,
190,
97,
82,
248,
187,
14,
130,
72,
105,
154,
224,
71,
158,
92,
4,
75,
52,
21,
121,
38,
167,
222,
41,
174,
146,
215,
132,
233,
210,
186,
93,
243,
197,
176,
191,
164,
59,
113,
68,
70,
43,
252,
235,
111,
213,
246,
20,
254,
124,
112,
90,
125,
253,
47,
24,
131,
22,
165,
145,
31,
5,
149,
116,
169,
193,
91,
74,
133,
109,
19,
7,
79,
78,
69,
178,
15,
201,
28,
166,
188,
236,
115,
144,
123,
207,
89,
143,
161,
249,
45,
242,
177,
0,
148,
55,
159,
208,
46,
156,
110,
40,
63,
128,
240,
61,
211,
37,
138,
181,
231,
66,
179,
199,
234,
247,
76,
17,
51,
3,
162,
172,
96
};
protected const int BlockSize = 16;
private byte[][] m_roundKeys;
public virtual string AlgorithmName => "ARIA";
public virtual void Init(bool forEncryption, ICipherParameters parameters)
{
KeyParameter keyParameter = parameters as KeyParameter;
if (keyParameter == null)
throw new ArgumentException("invalid parameter passed to ARIA init - " + Platform.GetTypeName(parameters));
m_roundKeys = KeySchedule(forEncryption, keyParameter.GetKey());
}
public virtual int GetBlockSize()
{
return 16;
}
public virtual int ProcessBlock(byte[] input, int inOff, byte[] output, int outOff)
{
if (m_roundKeys == null)
throw new InvalidOperationException("ARIA engine not initialised");
Check.DataLength(input, inOff, 16, "input buffer too short");
Check.OutputLength(output, outOff, 16, "output buffer too short");
byte[] array = new byte[16];
Array.Copy(input, inOff, array, 0, 16);
int num = 0;
int num2 = m_roundKeys.Length - 3;
while (num < num2) {
FO(array, m_roundKeys[num++]);
FE(array, m_roundKeys[num++]);
}
FO(array, m_roundKeys[num++]);
Xor(array, m_roundKeys[num++]);
SL2(array);
Xor(array, m_roundKeys[num]);
Array.Copy(array, 0, output, outOff, 16);
return 16;
}
protected static void A(byte[] z)
{
byte b = z[0];
byte b2 = z[1];
byte b3 = z[2];
byte b4 = z[3];
byte b5 = z[4];
byte b6 = z[5];
byte b7 = z[6];
byte b8 = z[7];
byte b9 = z[8];
byte b10 = z[9];
byte b11 = z[10];
byte b12 = z[11];
byte b13 = z[12];
byte b14 = z[13];
byte b15 = z[14];
byte b16 = z[15];
z[0] = (byte)(b4 ^ b5 ^ b7 ^ b9 ^ b10 ^ b14 ^ b15);
z[1] = (byte)(b3 ^ b6 ^ b8 ^ b9 ^ b10 ^ b13 ^ b16);
z[2] = (byte)(b2 ^ b5 ^ b7 ^ b11 ^ b12 ^ b13 ^ b16);
z[3] = (byte)(b ^ b6 ^ b8 ^ b11 ^ b12 ^ b14 ^ b15);
z[4] = (byte)(b ^ b3 ^ b6 ^ b9 ^ b12 ^ b15 ^ b16);
z[5] = (byte)(b2 ^ b4 ^ b5 ^ b10 ^ b11 ^ b15 ^ b16);
z[6] = (byte)(b ^ b3 ^ b8 ^ b10 ^ b11 ^ b13 ^ b14);
z[7] = (byte)(b2 ^ b4 ^ b7 ^ b9 ^ b12 ^ b13 ^ b14);
z[8] = (byte)(b ^ b2 ^ b5 ^ b8 ^ b11 ^ b14 ^ b16);
z[9] = (byte)(b ^ b2 ^ b6 ^ b7 ^ b12 ^ b13 ^ b15);
z[10] = (byte)(b3 ^ b4 ^ b6 ^ b7 ^ b9 ^ b14 ^ b16);
z[11] = (byte)(b3 ^ b4 ^ b5 ^ b8 ^ b10 ^ b13 ^ b15);
z[12] = (byte)(b2 ^ b3 ^ b7 ^ b8 ^ b10 ^ b12 ^ b13);
z[13] = (byte)(b ^ b4 ^ b7 ^ b8 ^ b9 ^ b11 ^ b14);
z[14] = (byte)(b ^ b4 ^ b5 ^ b6 ^ b10 ^ b12 ^ b15);
z[15] = (byte)(b2 ^ b3 ^ b5 ^ b6 ^ b9 ^ b11 ^ b16);
}
protected static void FE(byte[] D, byte[] RK)
{
Xor(D, RK);
SL2(D);
A(D);
}
protected static void FO(byte[] D, byte[] RK)
{
Xor(D, RK);
SL1(D);
A(D);
}
protected static byte[][] KeySchedule(bool forEncryption, byte[] K)
{
int num = K.Length;
if (num < 16 || num > 32 || (num & 7) != 0)
throw new ArgumentException("Key length not 128/192/256 bits.");
int num2 = (num >> 3) - 2;
byte[] rK = C[num2];
byte[] rK2 = C[(num2 + 1) % 3];
byte[] rK3 = C[(num2 + 2) % 3];
byte[] array = new byte[16];
byte[] array2 = new byte[16];
Array.Copy(K, 0, array, 0, 16);
Array.Copy(K, 16, array2, 0, num - 16);
byte[] array3 = new byte[16];
byte[] array4 = new byte[16];
byte[] array5 = new byte[16];
byte[] array6 = new byte[16];
Array.Copy(array, 0, array3, 0, 16);
Array.Copy(array3, 0, array4, 0, 16);
FO(array4, rK);
Xor(array4, array2);
Array.Copy(array4, 0, array5, 0, 16);
FE(array5, rK2);
Xor(array5, array3);
Array.Copy(array5, 0, array6, 0, 16);
FO(array6, rK3);
Xor(array6, array4);
int num3 = 12 + num2 * 2;
byte[][] array7 = new byte[num3 + 1][];
array7[0] = KeyScheduleRound(array3, array4, 19);
array7[1] = KeyScheduleRound(array4, array5, 19);
array7[2] = KeyScheduleRound(array5, array6, 19);
array7[3] = KeyScheduleRound(array6, array3, 19);
array7[4] = KeyScheduleRound(array3, array4, 31);
array7[5] = KeyScheduleRound(array4, array5, 31);
array7[6] = KeyScheduleRound(array5, array6, 31);
array7[7] = KeyScheduleRound(array6, array3, 31);
array7[8] = KeyScheduleRound(array3, array4, 67);
array7[9] = KeyScheduleRound(array4, array5, 67);
array7[10] = KeyScheduleRound(array5, array6, 67);
array7[11] = KeyScheduleRound(array6, array3, 67);
array7[12] = KeyScheduleRound(array3, array4, 97);
if (num3 > 12) {
array7[13] = KeyScheduleRound(array4, array5, 97);
array7[14] = KeyScheduleRound(array5, array6, 97);
if (num3 > 14) {
array7[15] = KeyScheduleRound(array6, array3, 97);
array7[16] = KeyScheduleRound(array3, array4, 109);
}
}
if (!forEncryption) {
ReverseKeys(array7);
for (int i = 1; i < num3; i++) {
A(array7[i]);
}
}
return array7;
}
protected static byte[] KeyScheduleRound(byte[] w, byte[] wr, int n)
{
byte[] array = new byte[16];
int num = n >> 3;
int num2 = n & 7;
int num3 = 8 - num2;
int num4 = wr[15 - num] & 255;
for (int i = 0; i < 16; i++) {
int num5 = wr[(i - num) & 15] & 255;
int num6 = (num4 << num3) | (num5 >> num2);
num6 ^= (w[i] & 255);
array[i] = (byte)num6;
num4 = num5;
}
return array;
}
protected static void ReverseKeys(byte[][] keys)
{
int num = keys.Length;
int num2 = num / 2;
int num3 = num - 1;
for (int i = 0; i < num2; i++) {
byte[] array = keys[i];
keys[i] = keys[num3 - i];
keys[num3 - i] = array;
}
}
protected static byte SB1(byte x)
{
return SB1_sbox[x & 255];
}
protected static byte SB2(byte x)
{
return SB2_sbox[x & 255];
}
protected static byte SB3(byte x)
{
return SB3_sbox[x & 255];
}
protected static byte SB4(byte x)
{
return SB4_sbox[x & 255];
}
protected static void SL1(byte[] z)
{
z[0] = SB1(z[0]);
z[1] = SB2(z[1]);
z[2] = SB3(z[2]);
z[3] = SB4(z[3]);
z[4] = SB1(z[4]);
z[5] = SB2(z[5]);
z[6] = SB3(z[6]);
z[7] = SB4(z[7]);
z[8] = SB1(z[8]);
z[9] = SB2(z[9]);
z[10] = SB3(z[10]);
z[11] = SB4(z[11]);
z[12] = SB1(z[12]);
z[13] = SB2(z[13]);
z[14] = SB3(z[14]);
z[15] = SB4(z[15]);
}
protected static void SL2(byte[] z)
{
z[0] = SB3(z[0]);
z[1] = SB4(z[1]);
z[2] = SB1(z[2]);
z[3] = SB2(z[3]);
z[4] = SB3(z[4]);
z[5] = SB4(z[5]);
z[6] = SB1(z[6]);
z[7] = SB2(z[7]);
z[8] = SB3(z[8]);
z[9] = SB4(z[9]);
z[10] = SB1(z[10]);
z[11] = SB2(z[11]);
z[12] = SB3(z[12]);
z[13] = SB4(z[13]);
z[14] = SB1(z[14]);
z[15] = SB2(z[15]);
}
protected static void Xor(byte[] z, byte[] x)
{
Bytes.XorTo(16, x, z);
}
}
}