Created
July 6, 2013 00:21
-
-
Save eqdw/5938000 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
//Input filename typedefs | |
#define SBOX "aes_sbox.txt" | |
#define INVSBOX "aes_inv_sbox.txt" | |
//Number of 32-bit words comprising the state | |
#define Nb 4 | |
//Number of 32-bit words comprising the key | |
#define Nk 4 | |
//Number of iterations | |
#define Nr 10 | |
//The magick numbers | |
#define MODPOLY 0x1B | |
//Yay programmatic interfaces! | |
typedef unsigned int word; | |
typedef unsigned char byte; | |
//PROTOTYPES | |
void printKeySchedule(void); | |
void initSBox(const char * filename); | |
void printState(void); | |
void subBytes(void); | |
void shiftRows(void); | |
void shiftLeft(int n); | |
void mixColumns(void); | |
byte x3(byte in); | |
byte xtime(byte in); | |
void addRoundKey(void); | |
word wordify(byte a, byte b, byte c, byte d); | |
void dewordify(word inword, byte * accum); | |
void keyExpansion(void); | |
word rotWord(word inword); | |
word subWord(word inword); | |
void encrypt(char * infile, char * inkey); | |
int main(void); | |
void initInvSBox(const char * filename); | |
byte xe(byte in); | |
byte xb(byte in); | |
byte xd(byte in); | |
byte x9(byte in); | |
void invMixColumns(void); | |
void invSubBytes(void); | |
void invShiftRows(void); | |
void shiftRight(int n); | |
void decrypt(void); | |
int roundNum; | |
byte state[4][4]; | |
byte sbox[256]; | |
byte invsbox[256]; | |
byte key[16]; | |
word w[44]; | |
//Round constants! | |
word Rcon[] = {0x00000000, 0x01000000, 0x02000000, 0x04000000, | |
0x08000000, 0x10000000, 0x20000000, 0x40000000, | |
0x80000000, 0x1B000000, 0x36000000}; | |
//////////////////////////////////////////////////////////// | |
/////////////////////UTILITY FUNCTIONS////////////////////// | |
//////////////////////////////////////////////////////////// | |
void printKeySchedule(void) | |
{ | |
int i; | |
for(i=0;i<44;i++) | |
{ | |
printf("%.8x ",w[i]); | |
if((i%4)==3) | |
printf("\n"); | |
} | |
printf("\n"); | |
} | |
void initInvSBox(const char * filename) | |
{ | |
FILE * infile = fopen(filename, "r"); | |
int i; | |
int temp[256]; | |
for(i=0;i<256;i++) | |
{ | |
fscanf(infile,"%x", &temp[i]); | |
} | |
for(i=0; i< 256; i++) | |
invsbox[i] = temp[i]; | |
fclose(infile); | |
} | |
void initSBox(const char * filename) | |
{ | |
FILE * infile = fopen(filename, "r"); | |
int i; | |
int temp[256]; | |
//reads one byte of the table at a time | |
for(i=0; i < 256; i++) | |
{ | |
fscanf(infile, "%x", &temp[i]); | |
} | |
//now apparently C hates reading in 1-byte numbers. So I had to read them in as | |
//ints, and now will be implicitly casting them. | |
//NOTE: This could make bad things happen under normal circumstances, because | |
//implicit cast from int->char makes data get lost. However, since we know | |
//that every value read in from the sbox data file is 0<=val<=255, this will | |
//NEVER occur | |
for(i=0; i< 256; i++) | |
sbox[i] = temp[i]; | |
fclose(infile); | |
} | |
//Utility method: | |
void printState(void) | |
{ | |
int i, j; | |
// printf("Current State:\n"); | |
for(i=0; i < 4; i++) | |
{ | |
for(j=0;j<4;j++) | |
{ | |
printf("%.2x ", state[i][j]); | |
} | |
printf("\n"); | |
} | |
printf("\n"); | |
} | |
//////////////////////////////////////////////////////////// | |
/////////////////END UTILITY FUNCTIONS////////////////////// | |
//////////////////////////////////////////////////////////// | |
/////////////////////////////////////////////////////// | |
//THE FOLLOWING SECTION IS WITH REGARDS TO ENCRYPTION// | |
/////////////////////////////////////////////////////// | |
void subBytes(void) | |
{ | |
int i,j; | |
for(i=0;i<4;i++) | |
for(j=0;j<4;j++) | |
state[i][j] = sbox[state[i][j]]; | |
} | |
/* | |
//alternative code: | |
void subBytes(void) | |
{ | |
int i; | |
for(i=0;i<16;i++) | |
state[i/4][i%4] = sbox[state[i/4][i%4]] | |
} | |
*/ | |
void shiftRows(void) | |
{ | |
int i,j; | |
for(i=0; i<4; i++) | |
for(j=i; j>0; j--) | |
shiftLeft(i); | |
} | |
//helper function. Shifts a row of state (specified by n) ONE shift left | |
void shiftLeft(int n) | |
{ | |
byte temp = state[n][0]; | |
state[n][0] = state[n][1]; | |
state[n][1] = state[n][2]; | |
state[n][2] = state[n][3]; | |
state[n][3] = temp; | |
} | |
//This one's the painful one :( | |
//I'll the the Matrix Mult now so the program doesn't have to | |
// | |
//let * = GF(2**8) multiplication and ^ = GF(2**8) addition | |
// | |
// for each column | |
// elem0 = (2*elem0) ^ (3*elem1) ^ elem2 ^ elem3 | |
// elem1 = elem0 ^ (2*elem1) ^ (3*elem2) ^ elem3 | |
// elem2 = elem0 ^ elem1 ^ (2*elem2) ^ (3*elem3) | |
// elem3 = (3*elem0) ^ elem1 ^ elem2 ^ (2*elem3) | |
// | |
//keep in mind that 3 * elem = (elem ^ (2*elem)) | |
void mixColumns(void) | |
{ | |
byte new[4]; | |
int i,j; | |
//for each column | |
for(i=0;i<4;i++) | |
{ | |
//zero out new[] just in case | |
for(j=0;j<4;j++) | |
new[j]=0; | |
new[0] = xtime(state[0][i]) ^ x3(state[1][i]) ^ state[2][i] ^ state[3][i]; | |
new[1] = state[0][i] ^ xtime(state[1][i]) ^ x3(state[2][i]) ^ state[3][i]; | |
new[2] = state[0][i] ^ state[1][i] ^ xtime(state[2][i]) ^ x3(state[3][i]); | |
new[3] = x3(state[0][i]) ^ state[1][i] ^ state[2][i] ^ xtime(state[3][i]); | |
state[0][i] = new[0]; | |
state[1][i] = new[1]; | |
state[2][i] = new[2]; | |
state[3][i] = new[3]; | |
} | |
} | |
//for conciseness | |
// multiplying by x**2 + x is the same as | |
// a left shift followed by an xor with the original value | |
byte x3(byte in) | |
{ | |
return ( in ^ xtime(in)); | |
} | |
//multiply by x in GF(2**8) | |
byte xtime(byte in) | |
{ | |
//check if we need to reduce | |
// 0x80 = 1000 0000 | |
int flag = (in & 0x80); | |
//mult by x (ie leftshift | |
in <<= 1; | |
if(flag /* != 0 */ ) | |
in ^= MODPOLY; | |
return in; | |
} | |
void addRoundKey(void) | |
{ | |
// printf("\n AddRoundKey() entered\n"); | |
int i,j; | |
word colKey; | |
byte colKeyBytes[4]; | |
//reversed the typical roles of i and j because we're indexing state | |
//as column-major (effectively). This reminds me so I dont' confuse myself | |
for(j=0;j<4;j++) | |
{ | |
//grab current round key word | |
colKey = w[roundNum*Nb + j]; | |
dewordify(colKey, colKeyBytes); | |
// printf(" column %d: %x %x %x %x\n", j, colKeyBytes[0], | |
// colKeyBytes[1], colKeyBytes[2], colKeyBytes[3]); | |
for(i=0;i<4;i++) | |
{ | |
state[i][j] = state[i][j] ^ colKeyBytes[i]; | |
} | |
} | |
} | |
/////////////////////////////////////////////////////// | |
//////////////////////END ENCRYPTION/////////////////// | |
/////////////////////////////////////////////////////// | |
/////////////////////////////////////////////////////////// | |
///////////////////DECRYPTION FUNCTIONS//////////////////// | |
/////////////////////////////////////////////////////////// | |
// 0 e | |
// 0000 1110 = x8(in) + x4(in) + xtime(in) | |
byte xe(byte in) | |
{ | |
return xtime(xtime(xtime(in))) ^ xtime(xtime(in)) ^ xtime(in); | |
} | |
// 0 b | |
// 0000 1011 = x8(in) + xtime(in) + in | |
byte xb(byte in) | |
{ | |
return xtime(xtime(xtime(in))) ^ xtime(in) ^ in; | |
} | |
// 0 d | |
// 0000 1101 = x8(in) + x4(in) + x | |
byte xd(byte in) | |
{ | |
return xtime(xtime(xtime(in))) ^ xtime(xtime(in)) ^ in; | |
} | |
// 0 9 | |
// 0000 1001 = x8(in) + x | |
byte x9(byte in) | |
{ | |
return xtime(xtime(xtime(in))) ^ in; | |
} | |
void invMixColumns(void) | |
{ | |
byte new[4]; | |
int i,j; | |
//for each column | |
for(i=0;i<4;i++) | |
{ | |
//zero out new[] just in case | |
for(j=0;j<4;j++) | |
new[j]=0; | |
new[0] = xe(state[0][i]) ^ xb(state[1][i]) ^ xd(state[2][i]) ^ x9(state[3][i]); | |
new[1] = x9(state[0][i]) ^ xe(state[1][i]) ^ xb(state[2][i]) ^ xd(state[3][i]); | |
new[2] = xd(state[0][i]) ^ x9(state[1][i]) ^ xe(state[2][i]) ^ xb(state[3][i]); | |
new[3] = xb(state[0][i]) ^ xd(state[1][i]) ^ x9(state[2][i]) ^ xe(state[3][i]); | |
state[0][i] = new[0]; | |
state[1][i] = new[1]; | |
state[2][i] = new[2]; | |
state[3][i] = new[3]; | |
} | |
} | |
void invSubBytes(void) | |
{ | |
int i,j; | |
for(i=0;i<4;i++) | |
for(j=0;j<4;j++) | |
state[i][j] = invsbox[state[i][j]]; | |
} | |
void invShiftRows(void) | |
{ | |
int i,j; | |
for(i=0; i<4; i++) | |
for(j=i; j>0; j--) | |
shiftRight(i); | |
} | |
void shiftRight(int n) | |
{ | |
byte temp = state[n][3]; | |
state[n][3] = state[n][2]; | |
state[n][2] = state[n][1]; | |
state[n][1] = state[n][0]; | |
state[n][0] = temp; | |
} | |
/////////////////////////////////////////////////////////// | |
//////////////////////END DECRYPTION/////////////////////// | |
/////////////////////////////////////////////////////////// | |
/////////////////////////////////////////////////////////// | |
//THE FOLLOWING SECTION IS WITH REGARDS TO KEY SCHEDULING// | |
/////////////////////////////////////////////////////////// | |
//turns 4 bytes into a word | |
word wordify(byte a, byte b, byte c, byte d) | |
{ | |
word rtn = a; | |
rtn <<= 8; | |
rtn += b; | |
rtn <<= 8; | |
rtn += c; | |
rtn <<= 8; | |
rtn += d; | |
return rtn; | |
} | |
//converts a word into an array of 4 bytes. | |
//Uses the stupid cumbersome pointer thing to return the array | |
void dewordify(word inword, byte * accum) | |
{ | |
/* printf("\n dewordify entered!\n"); */ | |
/* printf(" inword = %x\n", inword); */ | |
word mask = 0x000000FF; | |
int i; | |
for(i=3; i>=0; i--) | |
{ | |
/* printf(" inword & mask: %x\n", inword & mask); */ | |
accum[i] = (byte) inword & mask; | |
/* printf(" accum[%d] = %x\n", i, accum[i]); */ | |
/* printf(" inword before shift: %x\n", inword); */ | |
inword >>= 8; | |
/* printf(" inword after shift: %x\n", inword); */ | |
} | |
} | |
void keyExpansion(void) | |
{ | |
word temp; | |
int i; | |
for(i=0; i < Nk; i++) | |
{ | |
w[i] = wordify(key[4*i], key[4*i + 1], key[4*i + 2], key[4*i + 3]); | |
} | |
for(i = Nk; i < (Nb*(Nr+1)); i++) | |
{ | |
temp = w[i-1]; | |
// printf("DEBUG --- temp: %x\n", temp); | |
if((i % Nk) == 0) | |
{ | |
temp = rotWord(temp); | |
// printf("DEBUG --- after RotWord(): %x\n", temp); | |
temp = subWord(temp); | |
// printf("DEBUG --- after SubWord(): %x\n", temp); | |
// printf("DEBUG --- Rcon[%d]: %x\n", i/Nk, Rcon[i/Nk]); | |
temp ^= Rcon[i/Nk]; | |
// printf("DEBUG --- after XOR with Rcon: %x\n", temp); | |
} | |
// printf("DEBUG --- w[%d]: %x\n", i-Nk, w[i-Nk]); | |
// printf("DEBUG --- temp XOR w[%d]: %x\n", i-Nk, temp ^ w[i-Nk]); | |
w[i] = w[i-Nk] ^ temp; | |
} | |
} | |
//It's pretty much a transliteration from the FIPS 197 document | |
word rotWord(word inword) | |
{ | |
/* printf("\n rotWord() entered!\n"); */ | |
int i; | |
byte bytes[4]; | |
byte temp; | |
dewordify(inword, bytes); | |
/* printf(" dewordified %x\n", inword); */ | |
for(i=0;i<4;i++) | |
/* printf(" bytes[%d] = %x\n", i, bytes[i]); */ | |
temp = bytes[0]; | |
bytes[0] = bytes[1]; | |
bytes[1] = bytes[2]; | |
bytes[2] = bytes[3]; | |
bytes[3] = temp; | |
return wordify(bytes[0], bytes[1], bytes[2], bytes[3]); | |
} | |
//S-Boxes the crap out of those words! | |
word subWord(word inword) | |
{ | |
int i; | |
byte bytes[4]; | |
//dewordify | |
dewordify(inword, bytes); | |
//sub | |
for(i=0; i < 4; i++) | |
bytes[i] = sbox[bytes[i]]; | |
return wordify(bytes[0], bytes[1], bytes[2], bytes[3]); | |
} | |
/////////////////////////////////////////////////////// | |
///////////////END KEY SCHEDULING SECTION////////////// | |
/////////////////////////////////////////////////////// | |
/////////////////////////////////////////////////////// | |
//////////////////BEGIN MAENAM SECTION///////////////// | |
/////////////////////////////////////////////////////// | |
void encrypt(char * infile, char * inkey) | |
{ | |
printf("PlainText filename: %s\n", infile); | |
printf("Key filename: %s\n", inkey); | |
roundNum = 0; | |
int i,j; | |
//init state and key | |
int temp[4][4]; | |
int tempkey[16]; | |
FILE * pfile = fopen(infile,"r"); | |
for(j=0;j<4;j++) | |
for(i=0;i<4;i++) | |
{ | |
fscanf(pfile, "%x", &temp[i][j]); | |
state[i][j] = temp[i][j]; | |
} | |
fclose(pfile); | |
FILE * pkey = fopen(inkey, "r"); | |
for(i=0;i<16;i++) | |
{ | |
fscanf(pkey, "%x", &tempkey[i]); | |
key[i] = tempkey[i]; | |
} | |
fclose(pkey); | |
keyExpansion(); | |
printKeySchedule(); | |
//END STATE INIT | |
printf("Encryption starting!\n"); | |
printState(); | |
addRoundKey(); | |
printf("After initial addRoundKey:\n"); | |
printState(); | |
for(roundNum=1;roundNum<Nr;roundNum++) | |
{ | |
// printf("Round: %d\n", roundNum); | |
// printState() ; | |
// printf("After SubBytes:\n"); | |
subBytes() ; | |
// printState() ; | |
//printf("After ShiftRows:\n"); | |
shiftRows() ; | |
//printState() ; | |
//printf("After MixCloumns:\n"); | |
mixColumns() ; | |
//printState() ; | |
//printf("After AddRoundKey:\n"); | |
addRoundKey(); | |
printf("After Round %d\n", roundNum); | |
printState() ; | |
} | |
//printf("After final SubBytes:\n"); | |
subBytes(); | |
//printState(); | |
//printf("After final ShiftRows:\n"); | |
shiftRows(); | |
//printState(); | |
//printf("After final AddRoundKey:\n"); | |
addRoundKey(); | |
//printState(); | |
printf("\n\n FINAL CYPHER OUTPUT: "); | |
for(j=0;j<4;j++) | |
for(i=0;i<4;i++) | |
printf("%.2x ", state[i][j]); | |
printf("\n\n"); | |
} | |
//uses existing key, and cyphertext will be in state. | |
void decrypt(void) | |
{ | |
int i,j; | |
printf("Beginning decryption!\n"); | |
printState(); | |
addRoundKey(); | |
printf("After initial addRoundKey:\n"); | |
printState(); | |
for(roundNum=9; roundNum>=1;roundNum--) | |
{ | |
//printf("Round: %d\n", roundNum); | |
//printState() ; | |
//printf("After InvShiftRows:\n"); | |
invShiftRows() ; | |
//printState() ; | |
//printf("After InvSubBytes:\n"); | |
invSubBytes() ; | |
//printState() ; | |
//printf("After AddRoundKey:\n"); | |
addRoundKey() ; | |
//printState() ; | |
//printf("After InvMixColumns:\n"); | |
invMixColumns(); | |
printf("After round %d\n", roundNum); | |
printState() ; | |
} | |
//printf("After final InvShiftRows:\n"); | |
invShiftRows(); | |
//printState(); | |
//printf("After final InvSubBytes:\n"); | |
invSubBytes(); | |
//printState(); | |
//printf("After final AddRoundKey:\n"); | |
addRoundKey(); | |
//printState(); | |
printf("\n\n ORIGINAL PLAINTEXT: "); | |
for(j=0;j<4;j++) | |
for(i=0;i<4;i++) | |
printf("%.2x ", state[i][j]); | |
printf("\n\n"); | |
} | |
int main(void) | |
{ | |
initSBox(SBOX); | |
initInvSBox(INVSBOX); | |
encrypt("test1plaintext.txt", "test1key.txt"); | |
decrypt(); | |
encrypt("test2plaintext.txt", "test2key.txt"); | |
decrypt(); | |
encrypt("test3plaintext.txt", "test3key.txt"); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment