⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 aes.c

📁 AES在AVR单片机上的实现 资源要求 Program: 4492 bytes (6.9% Full) (.text + .data + .bootloader) Data: 7
💻 C
字号:
#include "aes.h"
//#include "crc.h"
unsigned char  expand_Key[EXPANDED_KEY_SIZE];	// expand key table
unsigned char  Seed_Key[KEYLENGTH] = {0};


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

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


unsigned char Multiply( unsigned char num, unsigned char factor )
{
	unsigned char mask = 1;
	unsigned char result = 0;

	while( mask != 0 ) 
	{
		// Check bit of factor given by mask.
		if( mask & factor ) 
		{
			// Add current multiple of num in GF(2).
			result ^= num;
		}

		// Shift mask to indicate next bit.
		mask <<= 1;

		// Double num.
       	num = (num << 1) ^ (num & 0x80 ? BPOLY : 0);
	}

	return result;
}

//
unsigned char DotProduct( unsigned char * vector1, unsigned char * vector2 )
{
	unsigned char result = 0;

	result ^= Multiply( *vector1++, *vector2++ );
	result ^= Multiply( *vector1++, *vector2++ );
	result ^= Multiply( *vector1++, *vector2++ );
	result ^= Multiply( *vector1  , *vector2   );

	return result;
}

void MixColumn( unsigned char * column )
{
	unsigned char row[8] = 
	{
		0x02, 0x03, 0x01, 0x01,
		0x02, 0x03, 0x01, 0x01
	}; // Prepare first row of matrix twice, to eliminate need for cycling.

	unsigned char result[4];
	
	// Take dot products of each matrix row and the column vector.
	result[0] = DotProduct( row+0, column );
	result[1] = DotProduct( row+3, column );
	result[2] = DotProduct( row+2, column );
	result[3] = DotProduct( row+1, column );

	// Copy temporary result to original column.
	column[0] = result[0];
	column[1] = result[1];
	column[2] = result[2];
	column[3] = result[3];
}


/***************************************************************************
|																		   |
| This routine applies the MixColumns diffusion operator to the whole 	   |
| state matrix. The code is used for both encryption and decryption.	   |
|																		   |
| Note: This routine is part of the encryption and decryption routines. You|
|  normally wont be interested in calling this routine directly.		   |
|																		   |
****************************************************************************/

void MixColumns( unsigned char * state )
{
	MixColumn( state + 0*4 );
	MixColumn( state + 1*4 );
	MixColumn( state + 2*4 );
	MixColumn( state + 3*4 );
}


// shift the data left
void CycleLeft( unsigned char * row )
{
	// Cycle 4 bytes in an array left once.
	unsigned char temp = row[0];
	row[0] = row[1];
	row[1] = row[2];
	row[2] = row[3];
	row[3] = temp;
}

// shift the data left one bit according to MSB
unsigned char shift1bit(unsigned char input)
{
   unsigned char b =0 ;
   if( input & 0x80)
       b = BPOLY;
   input=input<<1;
   b = input^b;
   return b ;
       
}


void InvMixColumn( unsigned char * column )
{
	unsigned char r_mix0, r_mix1, r_mix2, r_mix3;

	r_mix0 = column[1] ^ column[2] ^ column[3];
	r_mix1 = column[0] ^ column[2] ^ column[3];
	r_mix2 = column[0] ^ column[1] ^ column[3];
	r_mix3 = column[0] ^ column[1] ^ column[2];

	
 	/*column[0] = (column[0] << 1) ^ (column[0] & 0x80 ? BPOLY : 0);
 	column[1] = (column[1] << 1) ^ (column[1] & 0x80 ? BPOLY : 0);
   	column[2] = (column[2] << 1) ^ (column[2] & 0x80 ? BPOLY : 0);
   	column[3] = (column[3] << 1) ^ (column[3] & 0x80 ? BPOLY : 0);
    */
	column[0]= shift1bit(column[0]);
	column[1]= shift1bit(column[1]);
	column[2]= shift1bit(column[2]);
	column[3]= shift1bit(column[3]);
	
	r_mix0 ^= column[0] ^ column[1];
	r_mix1 ^= column[1] ^ column[2];
	r_mix2 ^= column[2] ^ column[3];
	r_mix3 ^= column[0] ^ column[3];

   	/*column[0] = (column[0] << 1) ^ (column[0] & 0x80 ? BPOLY : 0);
   	column[1] = (column[1] << 1) ^ (column[1] & 0x80 ? BPOLY : 0);
   	column[2] = (column[2] << 1) ^ (column[2] & 0x80 ? BPOLY : 0);
   	column[3] = (column[3] << 1) ^ (column[3] & 0x80 ? BPOLY : 0);
    */
	column[0]= shift1bit(column[0]);
	column[1]= shift1bit(column[1]);
	column[2]= shift1bit(column[2]);
	column[3]= shift1bit(column[3]);
	
	r_mix0 ^= column[0] ^ column[2];
	r_mix1 ^= column[1] ^ column[3];
	r_mix2 ^= column[0] ^ column[2];
	r_mix3 ^= column[1] ^ column[3];

   	/*column[0] = (column[0] << 1) ^ (column[0] & 0x80 ? BPOLY : 0);
   	column[1] = (column[1] << 1) ^ (column[1] & 0x80 ? BPOLY : 0);
   	column[2] = (column[2] << 1) ^ (column[2] & 0x80 ? BPOLY : 0);
   	column[3] = (column[3] << 1) ^ (column[3] & 0x80 ? BPOLY : 0);
	*/
	column[0]= shift1bit(column[0]);
	column[1]= shift1bit(column[1]);
	column[2]= shift1bit(column[2]);
	column[3]= shift1bit(column[3]);
	
	column[0] ^= column[1] ^ column[2] ^ column[3];
	r_mix0 ^= column[0];
	r_mix1 ^= column[0];
	r_mix2 ^= column[0];
	r_mix3 ^= column[0];

	column[0] = r_mix0;
	column[1] = r_mix1;
	column[2] = r_mix2;
	column[3] = r_mix3;
}

void InvMixColumns( unsigned char * state )
{
	InvMixColumn( state + 0*4 );
	InvMixColumn( state + 1*4 );
	InvMixColumn( state + 2*4 );
	InvMixColumn( state + 3*4 );
}


/***************************************************************************
|																		   |
| This routine is a substitution operation that takes each byte in the	   |
| State matrix and substitutes a new byte deternined by the Sbox table.	   |
|																		   |
****************************************************************************/

void SubBytes( unsigned char * bytes, unsigned char count )
{
	do 
	{
		*bytes = sBox[ *bytes ]; // Substitute every byte in state.
		bytes++;
	} while( --count );
}



void InvSubBytesAndXOR( unsigned char * bytes, unsigned char * key, unsigned char count )
{
	do 
	{
		*bytes = sBoxInv[ *bytes ] ^ *key; // Inverse substitute every byte in state and add key.
		bytes++;
		key++;
	} while( --count );
}


/***************************************************************************
|																		   |
|      This routine is a permutation operation that rotates bytes in the   |
| State matrix to the left.												   |
|																		   |
****************************************************************************/

void ShiftRows( unsigned char * state )
{
	unsigned char temp;

	// Note: State is arranged column by column.

	// Cycle second row left one time.
	temp = state[ 1 + 0*4 ];
	state[ 1 + 0*4 ] = state[ 1 + 1*4 ];
	state[ 1 + 1*4 ] = state[ 1 + 2*4 ];
	state[ 1 + 2*4 ] = state[ 1 + 3*4 ];
	state[ 1 + 3*4 ] = temp;

	// Cycle third row left two times.
	temp = state[ 2 + 0*4 ];
	state[ 2 + 0*4 ] = state[ 2 + 2*4 ];
	state[ 2 + 2*4 ] = temp;
	temp = state[ 2 + 1*4 ];
	state[ 2 + 1*4 ] = state[ 2 + 3*4 ];
	state[ 2 + 3*4 ] = temp;

	// Cycle fourth row left three times, ie. right once.
	temp = state[ 3 + 3*4 ];
	state[ 3 + 3*4 ] = state[ 3 + 2*4 ];
	state[ 3 + 2*4 ] = state[ 3 + 1*4 ];
	state[ 3 + 1*4 ] = state[ 3 + 0*4 ];
	state[ 3 + 0*4 ] = temp;
}


/***************************************************************************
|																		   |
|      This routine is a permutation operation that rotates bytes in the   |
| State matrix to the right.												   |
|																		   |
****************************************************************************/

void InvShiftRows( unsigned char * state )
{
	unsigned char temp;

	// Note: State is arranged column by column.

	// Cycle second row right one time.
	temp = state[ 1 + 3*4 ];
	state[ 1 + 3*4 ] = state[ 1 + 2*4 ];
	state[ 1 + 2*4 ] = state[ 1 + 1*4 ];
	state[ 1 + 1*4 ] = state[ 1 + 0*4 ];
	state[ 1 + 0*4 ] = temp;

	// Cycle third row right two times.
	temp = state[ 2 + 0*4 ];
	state[ 2 + 0*4 ] = state[ 2 + 2*4 ];
	state[ 2 + 2*4 ] = temp;
	temp = state[ 2 + 1*4 ];
	state[ 2 + 1*4 ] = state[ 2 + 3*4 ];
	state[ 2 + 3*4 ] = temp;

	// Cycle fourth row right three times, ie. left once.
	temp = state[ 3 + 0*4 ];
	state[ 3 + 0*4 ] = state[ 3 + 1*4 ];
	state[ 3 + 1*4 ] = state[ 3 + 2*4 ];
	state[ 3 + 2*4 ] = state[ 3 + 3*4 ];
	state[ 3 + 3*4 ] = temp;
}


// do count times XOR calculation
void XORBytes( unsigned char * bytes1, unsigned char * bytes2, unsigned char count )
{
	do 
	{
		*bytes1 ^= *bytes2; // Add in GF(2), ie. XOR.
		bytes1++;
		bytes2++;
	} while( --count );
}


// copy count bytes
void CopyBytes( unsigned char * to, unsigned char * from, unsigned char count )
{
	do 
	{
		*to = *from;
		to++;
		from++;
	} while( --count );
}


/***************************************************************************
|																		   |
|  The following routine implements the Rijndael key expansion algorithm.  |
|  Note: the key expansion is necessary for both encryption and decryption.|
|																		   |
****************************************************************************/

void KeyExpansion( unsigned char  * expandedKey )
{
	unsigned char temp[4];
	unsigned char i;
	unsigned char  Rcon[4] = { 0x01, 0x00, 0x00, 0x00 }; // The round constants used in subkey expansion .
	
	unsigned char  *key = Seed_Key;

	// Copy key to start of expanded key.
	i = KEYLENGTH;

	do  
	{
		*expandedKey = *key;
		expandedKey++;
		key++;
	} while( --i );

	// Prepare last 4 bytes of key in temp.
	expandedKey -= 4;
	temp[0] = *(expandedKey++);
	temp[1] = *(expandedKey++);
	temp[2] = *(expandedKey++);
	temp[3] = *(expandedKey++);

	// Expand key.
	i = KEYLENGTH;
	while( i < BLOCKSIZE*(ROUNDS+1) ) 
	{
		// Are we at the start of a multiple of the key size?
		if( (i % KEYLENGTH) == 0 ) 
		{
			CycleLeft( temp ); // Cycle left once.
			SubBytes( temp, 4 ); // Substitute each byte.
			XORBytes( temp, Rcon, 4 ); // Add constant in GF(2).
		//	*Rcon = (*Rcon << 1) ^ (*Rcon & 0x80 ? BPOLY : 0);
		    *Rcon = Multiply(*Rcon, 0x02);
		    
		}

		// Keysize larger than 24 bytes, ie. larger that 192 bits?
		//#if KEYLENGTH > 24
		// Are we right past a block size?
		//else if( (i % KEYLENGTH) == BLOCKSIZE ) {
		//	SubBytes( temp, 4 ); // Substitute each byte.
		//}
	    //#endif

		// Add bytes in GF(2) one KEYLENGTH away.
		XORBytes( temp, expandedKey - KEYLENGTH, 4 );

		// Copy result to current 4 bytes.
		*(expandedKey++) = temp[ 0 ];
		*(expandedKey++) = temp[ 1 ];
		*(expandedKey++) = temp[ 2 ];
		*(expandedKey++) = temp[ 3 ];

		i += 4; // Next 4 bytes.
	}	
}

void Cipher( unsigned char * block, unsigned char  * expandedKey )
{
	unsigned char round = ROUNDS-1;

	XORBytes( block, expandedKey, 16 );
	expandedKey += BLOCKSIZE;

	do 
	{
		SubBytes( block, 16 );
		ShiftRows( block );
		MixColumns( block );
		XORBytes( block, expandedKey, 16 );
		expandedKey += BLOCKSIZE;
	} while( --round );

	SubBytes( block, 16 );
	ShiftRows( block );
	XORBytes( block, expandedKey, 16 );
}


void InvCipher( unsigned char * block, unsigned char * expandedKey )
{
	unsigned char round = ROUNDS-1;
	expandedKey += BLOCKSIZE * ROUNDS;

	XORBytes( block, expandedKey, 16 );
	expandedKey -= BLOCKSIZE;

	do 
	{
		InvShiftRows( block );
		InvSubBytesAndXOR( block, expandedKey, 16 );
		expandedKey -= BLOCKSIZE;
		InvMixColumns( block );
	} while( --round );

	InvShiftRows( block );
	InvSubBytesAndXOR( block, expandedKey, 16 );
}

// creat sBox and sBoxInv table and use seed key to creat expandkey table
void aesInit( void )
{
    GetSeedKey();
	KeyExpansion( expand_Key );

}	
// init Seedkey
void GetSeedKey()
{
   unsigned int CRCVal = 0;
   unsigned char cnt;
   /*GetMacAddress(Seed_Key);
   //CRCVal = cal_crc(CRCVal, Seed_Key, 6);
   Seed_Key[6] = (CRCVal>>8) & 0xFF;
   Seed_Key[7] =  CRCVal& 0xFF;
   for(cnt=0; cnt<8; cnt++)
   {
      Seed_Key[cnt + 8] = ~Seed_Key[cnt];
    }*/
}

//aesBlockEncrypt(unsigned char * buffer
// buffer : string need to encrypt
// blocklen : multiple of 16
void BlockEncrypt(unsigned char * buffer, unsigned char blocklen)
{
  unsigned char multiplenum = blocklen / 16;
  unsigned char i;

  for(i = 0; i< multiplenum; i++)
  {
  	Cipher(buffer + i * 16,expand_Key);
  }
}

//aesBlockEncrypt(unsigned char * buffer
// buffer : string need to encrypt
// blocklen : multiple of 16

void BlockInvEncrypt(unsigned char * buffer, unsigned char blocklen)
{
  unsigned char multiplenum = blocklen / 16;
  unsigned char i;

  for(i = 0; i< multiplenum; i++)
  {
  	InvCipher(buffer + i * 16,expand_Key);
  }

}

//#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -