├── AES_Cipher.cpp ├── README.md ├── AES_Cipher.h ├── AES_Encrypt.c └── AES_Decrypt.c /AES_Cipher.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HUTOYP/AES128_ECB_PKCS5Padding/HEAD/AES_Cipher.cpp -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### AES128_ECB_PKCS5Padding 2 | 3 | **AES_Encrypt/Decrypt.c** 4 | C 实现的 AES128 加解密接口 5 | 6 | **AES_Cipher.h/.cpp** 7 | C++ 实现的 封装良好的 AES128 加解密接口 8 | -------------------------------------------------------------------------------- /AES_Cipher.h: -------------------------------------------------------------------------------- 1 | #ifndef _AES_CIPHER_H_ 2 | #define _AES_CIPHER_H_ 3 | 4 | namespace cipher 5 | { 6 | 7 | class AES_ECB_Cipher 8 | { 9 | public: 10 | explicit AES_ECB_Cipher(const unsigned char* key, bool use_cbc = false) : mKey(key), mState(NULL), use_cbc(use_cbc) {}; 11 | 12 | int encode(const unsigned char* src, uint32_t src_len, unsigned char* dest, uint32_t& dest_len); 13 | int decode(const unsigned char* src, uint32_t src_len, unsigned char* dest, uint32_t& dest_len); 14 | private: 15 | typedef uint8_t state_t[4][4]; 16 | uint8_t mRoundKey[240]; 17 | const unsigned char* mKey; 18 | state_t* mState; 19 | bool use_cbc; 20 | static const uint8_t scSbox[256]; 21 | static const uint8_t scRsbox[256]; 22 | static const uint8_t scRcon[255]; 23 | static const uint32_t KEYLEN; 24 | static const uint32_t NR; 25 | static const uint32_t NB; 26 | static const uint32_t NK; 27 | 28 | static inline uint8_t getSBoxValue(uint8_t num); 29 | static inline uint8_t getSBoxInvert(uint8_t num); 30 | static inline uint8_t xtime(uint8_t num); 31 | static inline uint8_t Multiply(uint8_t x, uint8_t y); 32 | 33 | void AddRoundKey(uint8_t round); 34 | void InvAddRoundKey(uint8_t round); 35 | void KeyExpansion(); 36 | 37 | void MixColumns(); 38 | void SubBytes(); 39 | void ShiftRows(); 40 | void Cipher(); 41 | void AES128_ECB_encrypt(const unsigned char* input, unsigned char* out); 42 | 43 | void InvMixColumns(); 44 | void InvSubBytes(); 45 | void InvShiftRows(); 46 | void InvCipher(); 47 | void AES128_ECB_decrypt(const unsigned char* input, unsigned char* out); 48 | }; 49 | 50 | } 51 | 52 | 53 | #endif 54 | -------------------------------------------------------------------------------- /AES_Encrypt.c: -------------------------------------------------------------------------------- 1 | /* 2 | ****************************************************************** 3 | ** Advanced Encryption Standard implementation in C. ** 4 | ** By Niyaz PK ** 5 | ** E-mail: niyazlife@gmail.com ** 6 | ** Downloaded from Website: www.hoozi.com ** 7 | ****************************************************************** 8 | This is the source code for encryption using the latest AES algorithm. 9 | AES algorithm is also called Rijndael algorithm. AES algorithm is 10 | recommended for non-classified by the National Institute of Standards 11 | and Technology(NIST), USA. Now-a-days AES is being used for almost 12 | all encryption applications all around the world. 13 | 14 | THE MAIN FEATURE OF THIS AES ENCRYPTION PROGRAM IS NOT EFFICIENCY; IT 15 | IS SIMPLICITY AND READABILITY. THIS SOURCE CODE IS PROVIDED FOR ALL 16 | TO UNDERSTAND THE AES ALGORITHM. 17 | 18 | Comments are provided as needed to understand the program. But the 19 | user must read some AES documentation to understand the underlying 20 | theory correctly. 21 | 22 | It is not possible to describe the complete AES algorithm in detail 23 | here. For the complete description of the algorithm, point your 24 | browser to: 25 | http://www.csrc.nist.gov/publications/fips/fips197/fips-197.pdf 26 | 27 | Find the Wikipedia page of AES at: 28 | http://en.wikipedia.org/wiki/Advanced_Encryption_Standard 29 | ****************************************************************** 30 | */ 31 | 32 | // Include stdio.h for standard input/output. 33 | // Used for giving output to the screen. 34 | #include 35 | 36 | // The number of columns comprising a state in AES. This is a constant in AES. Value=4 37 | #define Nb 4 38 | 39 | // The number of rounds in AES Cipher. It is simply initiated to zero. The actual value is recieved in the program. 40 | int Nr=0; 41 | 42 | // The number of 32 bit words in the key. It is simply initiated to zero. The actual value is recieved in the program. 43 | int Nk=0; 44 | 45 | // in - it is the array that holds the plain text to be encrypted. 46 | // out - it is the array that holds the key for encryption. 47 | // state - the array that holds the intermediate results during encryption. 48 | unsigned char in[16], out[16], state[4][4]; 49 | 50 | // The array that stores the round keys. 51 | unsigned char RoundKey[240]; 52 | 53 | // The Key input to the AES Program 54 | unsigned char Key[32]; 55 | 56 | int getSBoxValue(int num) 57 | { 58 | int sbox[256] = { 59 | //0 1 2 3 4 5 6 7 8 9 A B C D E F 60 | 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, //0 61 | 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, //1 62 | 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, //2 63 | 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, //3 64 | 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, //4 65 | 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, //5 66 | 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, //6 67 | 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, //7 68 | 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, //8 69 | 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, //9 70 | 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, //A 71 | 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, //B 72 | 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, //C 73 | 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, //D 74 | 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, //E 75 | 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 }; //F 76 | return sbox[num]; 77 | } 78 | 79 | // The round constant word array, Rcon[i], contains the values given by 80 | // x to th e power (i-1) being powers of x (x is denoted as {02}) in the field GF(28) 81 | // Note that i starts at 1, not 0). 82 | int Rcon[255] = { 83 | 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 84 | 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 85 | 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 86 | 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 87 | 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 88 | 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 89 | 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 90 | 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 91 | 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 92 | 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 93 | 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 94 | 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 95 | 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 96 | 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 97 | 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 98 | 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb }; 99 | 100 | // This function produces Nb(Nr+1) round keys. The round keys are used in each round to encrypt the states. 101 | void KeyExpansion() 102 | { 103 | int i,j; 104 | unsigned char temp[4],k; 105 | 106 | // The first round key is the key itself. 107 | for(i=0;i 6 && i % Nk == 4) 150 | { 151 | // Function Subword() 152 | { 153 | temp[0]=getSBoxValue(temp[0]); 154 | temp[1]=getSBoxValue(temp[1]); 155 | temp[2]=getSBoxValue(temp[2]); 156 | temp[3]=getSBoxValue(temp[3]); 157 | } 158 | } 159 | RoundKey[i*4+0] = RoundKey[(i-Nk)*4+0] ^ temp[0]; 160 | RoundKey[i*4+1] = RoundKey[(i-Nk)*4+1] ^ temp[1]; 161 | RoundKey[i*4+2] = RoundKey[(i-Nk)*4+2] ^ temp[2]; 162 | RoundKey[i*4+3] = RoundKey[(i-Nk)*4+3] ^ temp[3]; 163 | i++; 164 | } 165 | } 166 | 167 | // This function adds the round key to state. 168 | // The round key is added to the state by an XOR function. 169 | void AddRoundKey(int round) 170 | { 171 | int i,j; 172 | for(i=0;i<4;i++) 173 | { 174 | for(j=0;j<4;j++) 175 | { 176 | state[j][i] ^= RoundKey[round * Nb * 4 + i * Nb + j]; 177 | } 178 | } 179 | } 180 | 181 | // The SubBytes Function Substitutes the values in the 182 | // state matrix with values in an S-box. 183 | void SubBytes() 184 | { 185 | int i,j; 186 | for(i=0;i<4;i++) 187 | { 188 | for(j=0;j<4;j++) 189 | { 190 | state[i][j] = getSBoxValue(state[i][j]); 191 | 192 | } 193 | } 194 | } 195 | 196 | // The ShiftRows() function shifts the rows in the state to the left. 197 | // Each row is shifted with different offset. 198 | // Offset = Row number. So the first row is not shifted. 199 | void ShiftRows() 200 | { 201 | unsigned char temp; 202 | 203 | // Rotate first row 1 columns to left 204 | temp=state[1][0]; 205 | state[1][0]=state[1][1]; 206 | state[1][1]=state[1][2]; 207 | state[1][2]=state[1][3]; 208 | state[1][3]=temp; 209 | 210 | // Rotate second row 2 columns to left 211 | temp=state[2][0]; 212 | state[2][0]=state[2][2]; 213 | state[2][2]=temp; 214 | 215 | temp=state[2][1]; 216 | state[2][1]=state[2][3]; 217 | state[2][3]=temp; 218 | 219 | // Rotate third row 3 columns to left 220 | temp=state[3][0]; 221 | state[3][0]=state[3][3]; 222 | state[3][3]=state[3][2]; 223 | state[3][2]=state[3][1]; 224 | state[3][1]=temp; 225 | } 226 | 227 | // xtime is a macro that finds the product of {02} and the argument to xtime modulo {1b} 228 | #define xtime(x) ((x<<1) ^ (((x>>7) & 1) * 0x1b)) 229 | 230 | // MixColumns function mixes the columns of the state matrix 231 | void MixColumns() 232 | { 233 | int i; 234 | unsigned char Tmp,Tm,t; 235 | for(i=0;i<4;i++) 236 | { 237 | t=state[0][i]; 238 | Tmp = state[0][i] ^ state[1][i] ^ state[2][i] ^ state[3][i] ; 239 | Tm = state[0][i] ^ state[1][i] ; Tm = xtime(Tm); state[0][i] ^= Tm ^ Tmp ; 240 | Tm = state[1][i] ^ state[2][i] ; Tm = xtime(Tm); state[1][i] ^= Tm ^ Tmp ; 241 | Tm = state[2][i] ^ state[3][i] ; Tm = xtime(Tm); state[2][i] ^= Tm ^ Tmp ; 242 | Tm = state[3][i] ^ t ; Tm = xtime(Tm); state[3][i] ^= Tm ^ Tmp ; 243 | } 244 | } 245 | 246 | // Cipher is the main function that encrypts the PlainText. 247 | void Cipher() 248 | { 249 | int i,j,round=0; 250 | 251 | //Copy the input PlainText to state array. 252 | for(i=0;i<4;i++) 253 | { 254 | for(j=0;j<4;j++) 255 | { 256 | state[j][i] = in[i*4 + j]; 257 | } 258 | } 259 | 260 | // Add the First round key to the state before starting the rounds. 261 | AddRoundKey(0); 262 | 263 | // There will be Nr rounds. 264 | // The first Nr-1 rounds are identical. 265 | // These Nr-1 rounds are executed in the loop below. 266 | for(round=1;round 35 | 36 | // The number of columns comprising a state in AES. This is a constant in AES. Value=4 37 | #define Nb 4 38 | 39 | // The number of rounds in AES Cipher. It is simply initiated to zero. The actual value is recieved in the program. 40 | int Nr=0; 41 | 42 | // The number of 32 bit words in the key. It is simply initiated to zero. The actual value is recieved in the program. 43 | int Nk=0; 44 | 45 | // in - it is the array that holds the CipherText to be decrypted. 46 | // out - it is the array that holds the output of the for decryption. 47 | // state - the array that holds the intermediate results during decryption. 48 | unsigned char in[16], out[16], state[4][4]; 49 | 50 | // The array that stores the round keys. 51 | unsigned char RoundKey[240]; 52 | 53 | // The Key input to the AES Program 54 | unsigned char Key[32]; 55 | 56 | int getSBoxInvert(int num) 57 | { 58 | int rsbox[256] = 59 | { 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb 60 | , 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb 61 | , 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e 62 | , 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25 63 | , 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92 64 | , 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84 65 | , 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06 66 | , 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b 67 | , 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73 68 | , 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e 69 | , 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b 70 | , 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4 71 | , 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f 72 | , 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef 73 | , 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61 74 | , 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d }; 75 | 76 | return rsbox[num]; 77 | } 78 | 79 | int getSBoxValue(int num) 80 | { 81 | int sbox[256] = { 82 | //0 1 2 3 4 5 6 7 8 9 A B C D E F 83 | 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 84 | 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 85 | 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 86 | 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 87 | 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 88 | 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, 89 | 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, 90 | 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 91 | 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, 92 | 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, 93 | 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 94 | 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, 95 | 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 96 | 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 97 | 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 98 | 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 }; 99 | return sbox[num]; 100 | } 101 | 102 | // The round constant word array, Rcon[i], contains the values given by 103 | // x to th e power (i-1) being powers of x (x is denoted as {02}) in the field GF(2^8) 104 | // Note that i starts at 1, not 0). 105 | int Rcon[255] = { 106 | 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 107 | 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 108 | 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 109 | 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 110 | 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 111 | 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 112 | 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 113 | 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 114 | 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 115 | 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 116 | 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 117 | 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 118 | 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 119 | 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 120 | 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 121 | 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb }; 122 | 123 | // This function produces Nb(Nr+1) round keys. The round keys are used in each round to decrypt the states. 124 | void KeyExpansion() 125 | { 126 | int i,j; 127 | unsigned char temp[4],k; 128 | 129 | // The first round key is the key itself. 130 | for(i=0;i 6 && i % Nk == 4) 173 | { 174 | // Function Subword() 175 | { 176 | temp[0]=getSBoxValue(temp[0]); 177 | temp[1]=getSBoxValue(temp[1]); 178 | temp[2]=getSBoxValue(temp[2]); 179 | temp[3]=getSBoxValue(temp[3]); 180 | } 181 | } 182 | RoundKey[i*4+0] = RoundKey[(i-Nk)*4+0] ^ temp[0]; 183 | RoundKey[i*4+1] = RoundKey[(i-Nk)*4+1] ^ temp[1]; 184 | RoundKey[i*4+2] = RoundKey[(i-Nk)*4+2] ^ temp[2]; 185 | RoundKey[i*4+3] = RoundKey[(i-Nk)*4+3] ^ temp[3]; 186 | i++; 187 | } 188 | } 189 | 190 | // This function adds the round key to state. 191 | // The round key is added to the state by an XOR function. 192 | void AddRoundKey(int round) 193 | { 194 | int i,j; 195 | for(i=0;i<4;i++) 196 | { 197 | for(j=0;j<4;j++) 198 | { 199 | state[j][i] ^= RoundKey[round * Nb * 4 + i * Nb + j]; 200 | } 201 | } 202 | } 203 | 204 | // The SubBytes Function Substitutes the values in the 205 | // state matrix with values in an S-box. 206 | void InvSubBytes() 207 | { 208 | int i,j; 209 | for(i=0;i<4;i++) 210 | { 211 | for(j=0;j<4;j++) 212 | { 213 | state[i][j] = getSBoxInvert(state[i][j]); 214 | 215 | } 216 | } 217 | } 218 | 219 | // The ShiftRows() function shifts the rows in the state to the left. 220 | // Each row is shifted with different offset. 221 | // Offset = Row number. So the first row is not shifted. 222 | void InvShiftRows() 223 | { 224 | unsigned char temp; 225 | 226 | // Rotate first row 1 columns to right 227 | temp=state[1][3]; 228 | state[1][3]=state[1][2]; 229 | state[1][2]=state[1][1]; 230 | state[1][1]=state[1][0]; 231 | state[1][0]=temp; 232 | 233 | // Rotate second row 2 columns to right 234 | temp=state[2][0]; 235 | state[2][0]=state[2][2]; 236 | state[2][2]=temp; 237 | 238 | temp=state[2][1]; 239 | state[2][1]=state[2][3]; 240 | state[2][3]=temp; 241 | 242 | // Rotate third row 3 columns to right 243 | temp=state[3][0]; 244 | state[3][0]=state[3][1]; 245 | state[3][1]=state[3][2]; 246 | state[3][2]=state[3][3]; 247 | state[3][3]=temp; 248 | } 249 | 250 | // xtime is a macro that finds the product of {02} and the argument to xtime modulo {1b} 251 | #define xtime(x) ((x<<1) ^ (((x>>7) & 1) * 0x1b)) 252 | 253 | // Multiplty is a macro used to multiply numbers in the field GF(2^8) 254 | #define Multiply(x,y) (((y & 1) * x) ^ ((y>>1 & 1) * xtime(x)) ^ ((y>>2 & 1) * xtime(xtime(x))) ^ ((y>>3 & 1) * xtime(xtime(xtime(x)))) ^ ((y>>4 & 1) * xtime(xtime(xtime(xtime(x)))))) 255 | 256 | // MixColumns function mixes the columns of the state matrix. 257 | // The method used to multiply may be difficult to understand for the inexperienced. 258 | // Please use the references to gain more information. 259 | void InvMixColumns() 260 | { 261 | int i; 262 | unsigned char a,b,c,d; 263 | for(i=0;i<4;i++) 264 | { 265 | 266 | a = state[0][i]; 267 | b = state[1][i]; 268 | c = state[2][i]; 269 | d = state[3][i]; 270 | 271 | 272 | state[0][i] = Multiply(a, 0x0e) ^ Multiply(b, 0x0b) ^ Multiply(c, 0x0d) ^ Multiply(d, 0x09); 273 | state[1][i] = Multiply(a, 0x09) ^ Multiply(b, 0x0e) ^ Multiply(c, 0x0b) ^ Multiply(d, 0x0d); 274 | state[2][i] = Multiply(a, 0x0d) ^ Multiply(b, 0x09) ^ Multiply(c, 0x0e) ^ Multiply(d, 0x0b); 275 | state[3][i] = Multiply(a, 0x0b) ^ Multiply(b, 0x0d) ^ Multiply(c, 0x09) ^ Multiply(d, 0x0e); 276 | } 277 | } 278 | 279 | // InvCipher is the main function that decrypts the CipherText. 280 | void InvCipher() 281 | { 282 | int i,j,round=0; 283 | 284 | //Copy the input CipherText 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(Nr); 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=Nr-1;round>0;round--) 300 | { 301 | InvShiftRows(); 302 | InvSubBytes(); 303 | AddRoundKey(round); 304 | InvMixColumns(); 305 | } 306 | 307 | // The last round is given below. 308 | // The MixColumns function is not here in the last round. 309 | InvShiftRows(); 310 | InvSubBytes(); 311 | AddRoundKey(0); 312 | 313 | // The decryption 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 | void main() 324 | { 325 | int i; 326 | 327 | // Recieve the length of key here. 328 | while(Nr!=128 && Nr!=192 && Nr!=256) 329 | { 330 | printf("Enter the length of Key(128, 192 or 256 only): "); 331 | scanf("%d",&Nr); 332 | } 333 | // Calculate Nk and Nr from the recieved value. 334 | Nk = Nr / 32; 335 | Nr = Nk + 6; 336 | 337 | 338 | 339 | // Part 1 is for demonstrative purpose. The key and plaintext are given in the program itself. 340 | // Part 1: ******************************************************** 341 | 342 | // The array temp stores the key. 343 | // The array temp2 stores the plaintext. 344 | unsigned char temp[32] = {0x00 ,0x01 ,0x02 ,0x03 ,0x04 ,0x05 ,0x06 ,0x07 ,0x08 ,0x09 ,0x0a ,0x0b ,0x0c ,0x0d ,0x0e ,0x0f}; 345 | unsigned char temp2[16]= {0x69 ,0xc4 ,0xe0 ,0xd8 ,0x6a ,0x7b ,0x04 ,0x30 ,0xd8 ,0xcd ,0xb7 ,0x80 ,0x70 ,0xb4 ,0xc5 ,0x5a}; 346 | 347 | // Copy the Key and CipherText 348 | for(i=0;i