1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 // AESCrypt.cc
4 // -----------
5 // AES encryption implementation
6 //
7 // Design and Implementation by Bjoern Lemke
8 //
9 // (C)opyright 2010-2016 Bjoern Lemke
10 //
11 //
12 // IMPLEMENTATION MODULE
13 //
14 // Class: AESCrpyt
15 //
16 // Description: AES encryption
17 //              The code has been derived from
18 //
19 //              Niyaz PK
20 //              E-mail: niyazpk@gmail.com
21 //              Downloaded from Website: www.hoozi.com
22 //
23 // Status: CLEAN
24 //
25 ///////////////////////////////////////////////////////////////////////////////
26 
27 // Include stdio.h for standard input/output.
28 // Used for giving output to the screen.
29 // #include<stdio.h>
30 
31 #include "Exception.h"
32 #include "AESCrypt.h"
33 
34 // The number of columns comprising a state in AES. This is a constant in AES. Value=4
35 #define Nb 4
36 
37 // xtime is a macro that finds the product of {02} and the argument to xtime modulo {1b}
38 // #define xtime(x)   ((x<<1) ^ (((x>>7) & 1) * 0x1b))
39 
AESCrypt()40 AESCrypt::AESCrypt()
41 {
42 }
43 
AESCrypt(const Chain & keyString,int keyLen)44 AESCrypt::AESCrypt(const Chain& keyString, int keyLen)
45 {
46     // The number of rounds in AES Cipher. It is simply initiated to zero. The actual value is recieved in the program.
47     _Nr=0;
48     // The number of 32 bit words in the key. It is simply initiated to zero. The actual value is recieved in the program.
49     _Nk=0;
50 
51     _Nr=keyLen;
52 
53     // Calculate Nk and Nr from the received value.
54     _Nk = _Nr / 32;
55     _Nr = _Nk + 6;
56 
57     if ( keyString.length() < _Nk*4 )
58 	throw Exception(EXLOC, "Key string too short");
59 
60     // keyLen must be either 128,192 or 256
61     if ( keyLen != 128 && keyLen !=192 && keyLen != 256 )
62 	throw Exception(EXLOC, "Invalid keylen ( 128,192 or 256 are valid )");
63 
64     // Copy the Key and PlainText
65     for(int i=0; i<_Nk*4; i++)
66     {
67         _Key[i]=keyString[i];
68         // _in[i]=temp2[i];
69     }
70 
71     // The KeyExpansion routine must be called before encryption.
72     KeyExpansion();
73 
74 }
75 
~AESCrypt()76 AESCrypt::~AESCrypt()
77 {
78 }
79 
getSBoxValue(int num)80 unsigned char AESCrypt::getSBoxValue(int num)
81 {
82     unsigned char sbox[256] =   {
83 	//0     1    2      3     4    5     6     7      8    9     A      B    C     D     E     F
84 	0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, //0
85 	0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, //1
86 	0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, //2
87 	0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, //3
88 	0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, //4
89 	0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, //5
90 	0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, //6
91 	0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, //7
92 	0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, //8
93 	0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, //9
94 	0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, //A
95 	0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, //B
96 	0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, //C
97 	0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, //D
98 	0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, //E
99 	0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 }; //F
100     return sbox[num];
101 }
102 
103 // The round constant word array, Rcon[i], contains the values given by
104 // x to th e power (i-1) being powers of x (x is denoted as {02}) in the field GF(28)
105 // Note that i starts at 1, not 0).
getRconValue(int num)106 unsigned char AESCrypt::getRconValue(int num)
107 {
108     unsigned char rcon[255] = {
109 
110 	0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a,
111 	0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39,
112 	0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a,
113 	0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8,
114 	0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef,
115 	0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc,
116 	0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b,
117 	0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3,
118 	0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94,
119 	0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20,
120 	0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35,
121 	0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f,
122 	0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04,
123 	0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63,
124 	0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd,
125 	0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb  };
126     return rcon[num];
127 }
128 
129 // This function produces Nb(Nr+1) round keys. The round keys are used in each round to encrypt the states.
KeyExpansion()130 void AESCrypt::KeyExpansion()
131 {
132     int i,j;
133     unsigned char temp[4],k;
134 
135     // The first round key is the key itself.
136     for(i=0;i<_Nk;i++)
137     {
138         _RoundKey[i*4]=_Key[i*4];
139         _RoundKey[i*4+1]=_Key[i*4+1];
140         _RoundKey[i*4+2]=_Key[i*4+2];
141         _RoundKey[i*4+3]=_Key[i*4+3];
142     }
143 
144     // All other round keys are found from the previous round keys.
145     while (i < (Nb * (_Nr+1)))
146     {
147         for(j=0;j<4;j++)
148         {
149             temp[j]=_RoundKey[(i-1) * 4 + j];
150         }
151         if (i % _Nk == 0)
152         {
153             // This function rotates the 4 bytes in a word to the left once.
154             // [a0,a1,a2,a3] becomes [a1,a2,a3,a0]
155 
156             // Function RotWord()
157             {
158                 k = temp[0];
159                 temp[0] = temp[1];
160                 temp[1] = temp[2];
161                 temp[2] = temp[3];
162                 temp[3] = k;
163             }
164 
165             // SubWord() is a function that takes a four-byte input word and
166             // applies the S-box to each of the four bytes to produce an output word.
167 
168             // Function Subword()
169             {
170                 temp[0]=getSBoxValue(temp[0]);
171                 temp[1]=getSBoxValue(temp[1]);
172                 temp[2]=getSBoxValue(temp[2]);
173                 temp[3]=getSBoxValue(temp[3]);
174             }
175 
176             temp[0] =  temp[0] ^ getRconValue(i/_Nk);
177         }
178         else if (_Nk > 6 && i % _Nk == 4)
179         {
180             // Function Subword()
181             {
182                 temp[0]=getSBoxValue(temp[0]);
183                 temp[1]=getSBoxValue(temp[1]);
184                 temp[2]=getSBoxValue(temp[2]);
185                 temp[3]=getSBoxValue(temp[3]);
186             }
187         }
188         _RoundKey[i*4+0] = _RoundKey[(i-_Nk)*4+0] ^ temp[0];
189         _RoundKey[i*4+1] = _RoundKey[(i-_Nk)*4+1] ^ temp[1];
190         _RoundKey[i*4+2] = _RoundKey[(i-_Nk)*4+2] ^ temp[2];
191         _RoundKey[i*4+3] = _RoundKey[(i-_Nk)*4+3] ^ temp[3];
192         i++;
193     }
194 }
195 
196 // This function adds the round key to state.
197 // The round key is added to the state by an XOR function.
AddRoundKey(int round)198 void AESCrypt::AddRoundKey(int round)
199 {
200     int i,j;
201     for(i=0;i<4;i++)
202     {
203         for(j=0;j<4;j++)
204         {
205             _state[j][i] ^= _RoundKey[round * Nb * 4 + i * Nb + j];
206         }
207     }
208 }
209 
210 // The SubBytes Function Substitutes the values in the
211 // state matrix with values in an S-box.
SubBytes()212 void AESCrypt::SubBytes()
213 {
214     int i,j;
215     for(i=0;i<4;i++)
216     {
217         for(j=0;j<4;j++)
218         {
219             _state[i][j] = getSBoxValue(_state[i][j]);
220         }
221     }
222 }
223 
224 // The ShiftRows() function shifts the rows in the state to the left.
225 // Each row is shifted with different offset.
226 // Offset = Row number. So the first row is not shifted.
ShiftRows()227 void AESCrypt::ShiftRows()
228 {
229     unsigned char temp;
230 
231     // Rotate first row 1 columns to left
232     temp=_state[1][0];
233     _state[1][0]=_state[1][1];
234     _state[1][1]=_state[1][2];
235     _state[1][2]=_state[1][3];
236     _state[1][3]=temp;
237 
238     // Rotate second row 2 columns to left
239     temp=_state[2][0];
240     _state[2][0]=_state[2][2];
241     _state[2][2]=temp;
242 
243     temp=_state[2][1];
244     _state[2][1]=_state[2][3];
245     _state[2][3]=temp;
246 
247     // Rotate third row 3 columns to left
248     temp=_state[3][0];
249     _state[3][0]=_state[3][3];
250     _state[3][3]=_state[3][2];
251     _state[3][2]=_state[3][1];
252     _state[3][1]=temp;
253 }
254 
255 // MixColumns function mixes the columns of the state matrix
256 // The method used may look complicated, but it is easy if you know the underlying theory.
257 // Refer the documents specified above.
MixColumns()258 void AESCrypt::MixColumns()
259 {
260     int i;
261     unsigned char Tmp,Tm,t;
262     for(i=0;i<4;i++)
263     {
264         t=_state[0][i];
265         Tmp = _state[0][i] ^ _state[1][i] ^ _state[2][i] ^ _state[3][i] ;
266         Tm = _state[0][i] ^ _state[1][i] ; Tm = xtime(Tm); _state[0][i] ^= Tm ^ Tmp ;
267         Tm = _state[1][i] ^ _state[2][i] ; Tm = xtime(Tm); _state[1][i] ^= Tm ^ Tmp ;
268         Tm = _state[2][i] ^ _state[3][i] ; Tm = xtime(Tm); _state[2][i] ^= Tm ^ Tmp ;
269         Tm = _state[3][i] ^ t ; Tm = xtime(Tm); _state[3][i] ^= Tm ^ Tmp ;
270     }
271 }
272 
xtime(unsigned char x)273 unsigned char AESCrypt::xtime(unsigned char x)
274 {
275     unsigned char v = ((x<<1) ^ (((x>>7) & 1) * 0x1b));
276     return v;
277 }
278 
279 // Cipher is the main function that encrypts the PlainText.
Cipher()280 void AESCrypt::Cipher()
281 {
282     int i,j,round=0;
283 
284     //Copy the input PlainText to state array.
285     for(i=0;i<4;i++)
286     {
287         for(j=0;j<4;j++)
288         {
289             _state[j][i] = _in[i*4 + j];
290         }
291     }
292 
293     // Add the First round key to the state before starting the rounds.
294     AddRoundKey(0);
295 
296     // There will be Nr rounds.
297     // The first Nr-1 rounds are identical.
298     // These Nr-1 rounds are executed in the loop below.
299     for(round=1;round<_Nr;round++)
300     {
301         SubBytes();
302         ShiftRows();
303         MixColumns();
304         AddRoundKey(round);
305     }
306 
307     // The last round is given below.
308     // The MixColumns function is not here in the last round.
309     SubBytes();
310     ShiftRows();
311     AddRoundKey(_Nr);
312 
313     // The encryption process is over.
314     // Copy the state array to output array.
315     for(i=0;i<4;i++)
316     {
317         for(j=0;j<4;j++)
318         {
319             _out[i*4+j]=_state[j][i];
320         }
321     }
322 }
323 
324 #define MAXOUTBUF 1024
325 
encrypt(const Chain & val)326 Chain AESCrypt::encrypt(const Chain& val)
327 {
328 
329     // Receive the length of key here.
330     // while(Nr!=128 && Nr!=192 && Nr!=256)
331     // {
332     //     printf("Enter the length of Key(128, 192 or 256 only): ");
333     //    scanf("%d",&Nr);
334     // }
335 
336     // The array temp stores the key.
337     // The array temp2 stores the plaintext.
338     // unsigned char temp[16] = {0x00  ,0x01  ,0x02  ,0x03  ,0x04  ,0x05  ,0x06  ,0x07  ,0x08  ,0x09  ,0x0a  ,0x0b  ,0x0c  ,0x0d  ,0x0e  ,0x0f};
339     // unsigned char temp2[16]= {0x00  ,0x11  ,0x22  ,0x33  ,0x44  ,0x55  ,0x66  ,0x77  ,0x88  ,0x99  ,0xaa  ,0xbb  ,0xcc  ,0xdd  ,0xee  ,0xff};
340 
341     char outBuf[MAXOUTBUF];
342 
343     int i;
344     int offset=0;
345 
346     for ( i=0; i<val.length(); i+=16 )
347     {
348 
349 	int j;
350 
351 	// Copy the Key and PlainText
352 	for(j=0; j<16; j++)
353 	{
354 	    if ( i+j < val.length() )
355 		_in[j]=val[i + j];
356 	    else
357 		_in[j]=0;
358 	}
359 
360 	// The next function call encrypts the PlainText with the Key using AES algorithm.
361 	Cipher();
362 
363 	// Output the encrypted text.
364 
365 	for(j=0; j<16; j++)
366 	{
367 	    // outBuf[i*16+j] = _out[j];
368 	    // cout << "Pos=" << i+j << " Val=" << (int)_out[j] << endl;
369 	    sprintf(outBuf+offset, "%02x", _out[j]);
370 	    offset=offset+2;
371 
372 	    // outBuf[i*16+j+1] = 0;
373 	}
374     }
375 
376     Chain outString(outBuf);
377     return outString;
378 }
379