Hello,

I am new to this forum...
If anyone knows on AES and its s/w optimization techniques in c++ please help me out
I am using the AES code to encrypt and decrypt data..
In my code the plaintext is given in the main program itself it is in hexadecimal and i need to change it that is use files of different sizes, encrypt text such as: adv encryption standard and also encrypt images..

Here is the code in the main program:-

// Receive the length of key here.
    while(Nr!=128 && Nr!=192 && Nr!=256)
    {
        cout<<"Enter the length of Key(128, 192 or 256 only): ";
        cin>>Nr;
    }
	    
    // Calculate Nk and Nr from the received value.
    Nk = Nr / 32;
    Nr = Nk + 6;

*********************************************************
 // The array temp stores the key.
    // The array temp2 stores the plaintext.
    unsigned char temp[16] = {0x00  ,0x01  ,0x02  ,0x03  ,0x04  ,0x05  ,0x06  ,0x07  ,0x08  ,0x09  ,0x0a  ,0x0b  ,0x0c  ,0x0d  ,0x0e  ,0x0f};
    unsigned char temp2[16]= {0x00  ,0x11  ,0x22  ,0x33  ,0x44  ,0x55  ,0x66  ,0x77  ,0x88  ,0x99  ,0xaa  ,0xbb  ,0xcc  ,0xdd  ,0xee  ,0xff};
    
*********************************************************
// If anyone knows how to change this option for prompting for an input file or image

    // Copy the Key and PlainText
    for(i=0;i<Nk*4;i++)
    {
        Key[i]=temp[i];
        in[i]=temp2[i];
    }
KeyExpansion();
 Cipher();

cout<<"Cipher text: ";

please help me out...

So you open a file, and read 16 bytes into a buffer, then encrypt that, save 16 bytes to the output file.
Repeat doing that until you reach the end of the file.

But as yet, you've implemented almost nothing of AES.

Thnks for thx reply,

hmm no in fact i have the AES codes its the latest version which is only for understanding the AES operations & its for simplicity:-
I am posting the codes:-

In the main function i want to change the option of the plaintext from encrypting it in hexadecimal that is the program will prompt for choosing a file for encryption which cantain text messages and also to encrypt an image..

I am forwarding the AES codes:-

#include<iostream.h>
#include<iomanip.h>
#include<stdio.h>

// The number of columns comprising a state in AES. This is a constant in AES. Value=4
#define Nb 4

// The number of rounds in AES Cipher. It is simply initiated to zero. The actual value is recieved in the program.
int Nr=0;

// The number of 32 bit words in the key. It is simply initiated to zero. The actual value is recieved in the program.
int Nk=0;

// in - it is the array that holds the plain text to be encrypted.
// out - it is the array that holds the output CipherText after encryption.
// state - the array that holds the intermediate results during encryption.
unsigned char in[16], out[16], state[4][4];

// The array that stores the round keys.
unsigned char RoundKey[240];

// The Key input to the AES Program
unsigned char Key[32];

int getSBoxValue(int num)
{
    int sbox[256] =   {
    //0     1    2      3     4    5     6     7      8    9     A      B    C     D     E     F
    0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, //0
    0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, //1
    0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, //2
    0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, //3
    0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, //4
    0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, //5
    0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, //6
    0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, //7
    0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, //8
    0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, //9
    0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, //A
    0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, //B
    0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, //C
    0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, //D
    0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, //E
    0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 }; //F
    return sbox[num];
}

// The round constant word array, Rcon[i], contains the values given by
// x to the power (i-1) being powers of x (x is denoted as {02}) in the field GF(28)
// Note that i starts at 1, not 0).
int Rcon[255] = {
    0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a,
    0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39,
    0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a,
    0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8,
    0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef,
    0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc,
    0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b,
    0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3,
    0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94,
    0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20,
    0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35,
    0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f,
    0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04,
    0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63,
    0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd,
    0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb  };

// This function produces Nb(Nr+1) round keys. The round keys are used in each round to encrypt the states.
void KeyExpansion()
{
    int i,j;
    unsigned char temp[4],k;

    // The first round key is the key itself.
    for(i=0;i<Nk;i++)
    {
        RoundKey[i*4]=Key[i*4];
        RoundKey[i*4+1]=Key[i*4+1];
        RoundKey[i*4+2]=Key[i*4+2];
        RoundKey[i*4+3]=Key[i*4+3];
    }

    // All other round keys are found from the previous round keys.
    while (i < (Nb * (Nr+1)))
    {
        for(j=0;j<4;j++)
        {
            temp[j]=RoundKey[(i-1) * 4 + j];
        }
        if (i % Nk == 0)
        {
            // This function rotates the 4 bytes in a word to the left once.
            // [a0,a1,a2,a3] becomes [a1,a2,a3,a0]

            // Function RotWord()
            {
                k = temp[0];
                temp[0] = temp[1];
                temp[1] = temp[2];
                temp[2] = temp[3];
                temp[3] = k;
            }

            // SubWord() is a function that takes a four-byte input word and
            // applies the S-box to each of the four bytes to produce an output word.

            // Function Subword()
            {
                temp[0]=getSBoxValue(temp[0]);
                temp[1]=getSBoxValue(temp[1]);
                temp[2]=getSBoxValue(temp[2]);
                temp[3]=getSBoxValue(temp[3]);
            }

            temp[0] =  temp[0] ^ Rcon[i/Nk];
        }
        else if (Nk > 6 && i % Nk == 4)
        {
            // Function Subword()
            {
                temp[0]=getSBoxValue(temp[0]);
                temp[1]=getSBoxValue(temp[1]);
                temp[2]=getSBoxValue(temp[2]);
                temp[3]=getSBoxValue(temp[3]);
            }
        }
        RoundKey[i*4+0] = RoundKey[(i-Nk)*4+0] ^ temp[0];
        RoundKey[i*4+1] = RoundKey[(i-Nk)*4+1] ^ temp[1];
        RoundKey[i*4+2] = RoundKey[(i-Nk)*4+2] ^ temp[2];
        RoundKey[i*4+3] = RoundKey[(i-Nk)*4+3] ^ temp[3];
        i++;
    }
}

// This function adds the round key to state.
// The round key is added to the state by an XOR function.
void AddRoundKey(int round)
{
    int i,j;
    for(i=0;i<4;i++)
    {
        for(j=0;j<4;j++)
        {
            state[j][i] ^= RoundKey[round * Nb * 4 + i * Nb + j];
        }
    }
}

// The SubBytes Function Substitutes the values in the
// state matrix with values in an S-box.
void SubBytes()
{
    int i,j;
    for(i=0;i<4;i++)
    {
        for(j=0;j<4;j++)
        {
            state[i][j] = getSBoxValue(state[i][j]);

        }
    }
}

// The ShiftRows() function shifts the rows in the state to the left.
// Each row is shifted with different offset.
// Offset = Row number. So the first row is not shifted.
void ShiftRows()
{
    unsigned char temp;

    // Rotate first row 1 columns to left
    temp=state[1][0];
    state[1][0]=state[1][1];
    state[1][1]=state[1][2];
    state[1][2]=state[1][3];
    state[1][3]=temp;

    // Rotate second row 2 columns to left
    temp=state[2][0];
    state[2][0]=state[2][2];
    state[2][2]=temp;

    temp=state[2][1];
    state[2][1]=state[2][3];
    state[2][3]=temp;

    // Rotate third row 3 columns to left
    temp=state[3][0];
    state[3][0]=state[3][3];
    state[3][3]=state[3][2];
    state[3][2]=state[3][1];
    state[3][1]=temp;
}

// xtime is a macro that finds the product of {02} and the argument to xtime modulo {1b}
#define xtime(x)   ((x<<1) ^ (((x>>7) & 1) * 0x1b))

// MixColumns function mixes the columns of the state matrix
// The method used may look complicated, but it is easy if you know the underlying theory.
// Refer the documents specified above.
void MixColumns()
{
    int i;
    unsigned char Tmp,Tm,t;
    for(i=0;i<4;i++)
    {
        t=state[0][i];
        Tmp = state[0][i] ^ state[1][i] ^ state[2][i] ^ state[3][i] ;
        Tm = state[0][i] ^ state[1][i] ; Tm = xtime(Tm); state[0][i] ^= Tm ^ Tmp ;
        Tm = state[1][i] ^ state[2][i] ; Tm = xtime(Tm); state[1][i] ^= Tm ^ Tmp ;
        Tm = state[2][i] ^ state[3][i] ; Tm = xtime(Tm); state[2][i] ^= Tm ^ Tmp ;
        Tm = state[3][i] ^ t ; Tm = xtime(Tm); state[3][i] ^= Tm ^ Tmp ;
    }
}

// Cipher is the main function that encrypts the PlainText.
void Cipher()
{
    int i,j,round=0;

    //Copy the input PlainText to state array.
    for(i=0;i<4;i++)
    {
        for(j=0;j<4;j++)
        {
            state[j][i] = in[i*4 + j];
        }
    }

    // Add the First round key to the state before starting the rounds.
    AddRoundKey(0);

    // There will be Nr rounds.
    // The first Nr-1 rounds are identical.
    // These Nr-1 rounds are executed in the loop below.
    for(round=1;round<Nr;round++)
    {
        SubBytes();
        ShiftRows();
        MixColumns();
        AddRoundKey(round);
    }

    // The last round is given below.
    // The MixColumns function is not here in the last round.
    SubBytes();
    ShiftRows();
    AddRoundKey(Nr);

    // The encryption process is over.
    // Copy the state array to output array.
    for(i=0;i<4;i++)
    {
        for(j=0;j<4;j++)
        {
            out[i*4+j]=state[j][i];
        }
    }
}
void main()
{
    int i;



    // Receive the length of key here.
    while(Nr!=128 && Nr!=192 && Nr!=256)
    {
        printf("Enter the length of Key(128, 192 or 256 only): ");
        scanf("%d",&Nr);
    }


    // Calculate Nk and Nr from the received value.
    Nk = Nr / 32;
    Nr = Nk + 6;



// Part 1 is for demonstrative purpose. The key and plaintext are given in the program itself.
//     Part 1: ********************************************************

    // The array temp stores the key.
    // The array temp2 stores the plaintext.
    unsigned char temp[16] = {0x00  ,0x01  ,0x02  ,0x03  ,0x04  ,0x05  ,0x06  ,0x07  ,0x08  ,0x09  ,0x0a  ,0x0b  ,0x0c  ,0x0d  ,0x0e  ,0x0f};
    unsigned char temp2[16]= {0x00  ,0x11  ,0x22  ,0x33  ,0x44  ,0x55  ,0x66  ,0x77  ,0x88  ,0x99  ,0xaa  ,0xbb  ,0xcc  ,0xdd  ,0xee  ,0xff};

    // Copy the Key and PlainText
    for(i=0;i<Nk*4;i++)
    {
        Key[i]=temp[i];
        in[i]=temp2[i];
    }

//           *********************************************************




// Uncomment Part 2 if you need to read Key and PlainText from the keyboard.
//     Part 2: ********************************************************
/*
    //Clear the input buffer
    flushall();

    //Recieve the Key from the user
    printf("Enter the Key in hexadecimal: ");
    for(i=0;i<Nk*4;i++)
    {
        scanf("%x",&Key[i]);
    }

    printf("Enter the PlainText in hexadecimal: ");
    for(i=0;i<Nb*4;i++)
    {
        scanf("%x",&in[i]);
    }
*/
//             ********************************************************


    // The KeyExpansion routine must be called before encryption.
    KeyExpansion();

    // The next function call encrypts the PlainText with the Key using AES algorithm.
    Cipher();

    // Output the encrypted text.
    printf("\nText after encryption:\n");
    for(i=0;i<Nk*4;i++)
    {
        printf("%02x ",out[i]);
    }
    printf("\n\n");

}

How to change the plaintext in the main function i.e the program will prompt for a file or image for encryption..

Well the first thing to do would be to turn those parameterless functions and global variables into something which used parameters.

That would make it a lot easier to switch from say
- a pointer to a block of test data
to
- a pointer to a block of data read from a file.

Hmm how can we do it could you just give an example...
If we are using files which contain text messages of different sizes..
How is it possible to change the plaintext from the hexadecimal numbers to text for the program to run..
Also do u have an idea of how to read the data from an image which is used for encryption
i.e hw an image can be encrypted using the code

char hex[] = { 0x41, 0x42, 0x43 };
char dec[] = { 65, 66, 67 };
char chr[] = { 'A', 'B', 'C' };

Guess what the difference is between these three.

> Also do u have an idea of how to read the data from an image
The same as for printable text, or your arrays. It makes no difference to the algorithm what the bytes are, or where they came from.

> If we are using files which contain text messages of different sizes..
Like I said in the first reply, read the file in fixed sized blocks (as specified by your algorithm), then encrypt that block.

> Hmm how can we do it could you just give an example...
Change
Cypher();
into say
Cypher( inputBlock, inputSize, outputBlock, key, keySize );

Ok hmm i am using files for ecrypting the data i.e the key is saved on the key.txt file and it is opened for copying the bytes in the array Key in the program..
I am getting error mesages:-
binary '=' : no operator defined which takes a right-hand operand of type 'class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >' (or there is no acceptable conversion)
mismatch in formal parameter list

unsigned char temp[16],temp2[16];
string line,line1;

// Receive the length of key here.
    while(Nr!=128 && Nr!=192 && Nr!=256)
    {
        printf("Enter the length of Key(128, 192 or 256 only): ");
        scanf("%d",&Nr);
    }
	    
    // Calculate Nk and Nr from the received value.
    Nk = Nr / 32;
    Nr = Nk + 6;

ifstream myfile ("key.txt");
  if (myfile.is_open())
  {
	  while (! myfile.eof() )
    {      
		 getline (myfile,line);
         temp[16]=line;
				 
	 }
     
    myfile.close();
  }
  else 
	  cout << "Unable to open file";

ifstream myfile1 ("plaintext.txt");
  if (myfile1.is_open())
  {
	  while (! myfile1.eof() )
    {
		getline (myfile1,line1);
		temp2[16]=line1;
		      
	 }
     
    myfile1.close();
  }
  else 
	printf("Unable to open file");

 // Copy the Key and PlainText
    for(i=0;i<Nk*4;i++)
    {
        Key[i]=temp[i];
        in[i]=temp2[i];
    }

Could you help me out for the conversion errors..

key.txt: {0x00 ,0x01 ,0x02 ,0x03 ,0x04 ,0x05 ,0x06 ,0x07 ,0x08 ,0x09 ,0x0a ,0x0b ,0x0c ,0x0d ,0x0e ,0x0f}

> temp[16]=line;
Maybe begin with learning a bit more C or C++ before rushing headlong into something fairly complicated like AES?

To copy a string from a C++ string to a C char array (ignoring overflow) strcpy( temp, line.c_str() ); Though all the code you've posted up to now has been C all the way, so why are you complicating it by mixing in a bit of C++ as well?

Eg.

FILE *fp = fopen("file.txt", "rb" );
while ( (n=fread(line, 1, sizeof line, fp)) != 0 ) {
    // we're reading the file 16 bytes at a time (we don't care much more than that)
    // n will be the number of bytes read, which will be >0 and <= 16 at the end of the file.
    // do stuff with 'n' bytes.
}

Hello,

The code

strcpy( temp, line.c_str() );

solved the problem...Thnx Salem
But now the text to be encrypted is limited to 16 bytes only..
As the state of AES is of fixed size 128 bits = 16 bytes the program works well for the 1st 16 bytes now suppose we have to encrypt a long text of message how will the program place each byte in the array state for encryption with the key...

For encrypting an image suppose we have to read the data from the image and store the values on a file.txt then each value is placed in the state array for encryption with the key..

Can anyone help me out which code to use to read the data from an image and store the values in a file...

Hi,

can anyone help me out with the Key size in the AES...

// Receive the length of key here.
    while(Nr!=128 && Nr!=192 && Nr!=256)
    {
        printf("Enter the length of Key(128, 192 or 256 only): ");
        scanf("%d",&Nr);
    }

	cout<<endl;
	    
    // Calculate Nk and Nr from the received value.
    Nk = Nr / 32;
    Nr = Nk + 6;

	string line1;
	ifstream myfile1 ("plaintext.txt");

    if (myfile1.is_open())
  {
    while (! myfile1.eof() )
    {
	        getline(myfile1,line1);
		
		strcpy( temp2, line1.c_str() );
	}
    myfile1.close();
  }

  else cout << "Unable to open file"; 

	string line2;
	ifstream myfile2 ("key.txt");

  
  if (myfile2.is_open())
  {
    while (! myfile2.eof() )
    {
	        getline(myfile2,line2);
		
		strcpy( temp, line2.c_str() );
	}
    myfile2.close();
  }

  else cout << "Unable to open file"; 


  // Copy the Key and PlainText
    for(i=0;i<Nk*4;i++)
    {
        Key[i]=temp[i];	
		in[i]=temp2[i];		
    }

	 cout<<"Key       : "<<Key<<endl<<endl;
     cout<<"Plaintext : "<<in<<endl<<endl;

key.txt :- 0123456789abcdef
plaintext.txt :- ghijklmnopqrstuv
ciphertext.txt :- ################

Suppose we choose the key:128

Key:- 0123456789abcdef
plaintext:- ghijklmnopqrstuv

with key: 192

Key:- 0123456789abcdef
plaintext:- ghijklmnopqrstuv01234567

with key: 256

Key:- 0123456789abcdef
plaintext:- ghijklmnopqrstuv0123456789abcdef

My question is:-

When we are choosing the key size 192/256 the size of the key is not supposed to increase by 8 and 16 respectively instead of the plaintext..

This article has been dead for over six months. Start a new discussion instead.