📄 08d2.c
字号:
}
}
// 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 InvShiftRows()
{
unsigned char temp;
// Rotate first row 1 columns to right
temp=state[1][3];
state[1][3]=state[1][2];
state[1][2]=state[1][1];
state[1][1]=state[1][0];
state[1][0]=temp;
// Rotate second row 2 columns to right
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 right
temp=state[3][0];
state[3][0]=state[3][1];
state[3][1]=state[3][2];
state[3][2]=state[3][3];
state[3][3]=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))
// Multiplty is a macro used to multiply numbers in the field GF(2^8)
#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))))))
// MixColumns function mixes the columns of the state matrix.
// The method used to multiply may be difficult to understand for the inexperienced.
// Please use the references to gain more information.
void InvMixColumns()
{
int i;
unsigned char a,b,c,d;
for(i=0;i<4;i++)
{
a = state[0][i];
b = state[1][i];
c = state[2][i];
d = state[3][i];
state[0][i] = Multiply(a, 0x0e) ^ Multiply(b, 0x0b) ^ Multiply(c, 0x0d) ^ Multiply(d, 0x09);
state[1][i] = Multiply(a, 0x09) ^ Multiply(b, 0x0e) ^ Multiply(c, 0x0b) ^ Multiply(d, 0x0d);
state[2][i] = Multiply(a, 0x0d) ^ Multiply(b, 0x09) ^ Multiply(c, 0x0e) ^ Multiply(d, 0x0b);
state[3][i] = Multiply(a, 0x0b) ^ Multiply(b, 0x0d) ^ Multiply(c, 0x09) ^ Multiply(d, 0x0e);
}
}
// InvCipher is the main function that decrypts the CipherText.
void InvCipher()
{
int i,j,round=0;
//Copy the input CipherText 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(Nr);
// There will be Nr rounds.
// The first Nr-1 rounds are identical.
// These Nr-1 rounds are executed in the loop below.
for(round=Nr-1;round>0;round--)
{
InvShiftRows();
InvSubBytes();
AddRoundKey(round);
InvMixColumns();
}
// The last round is given below.
// The MixColumns function is not here in the last round.
InvShiftRows();
InvSubBytes();
AddRoundKey(0);
// The decryption 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];
}
}
}
char toASCIICode(char x) //This function returns the ASCII Code of the Symbol used to represent the Hexadecimal Digit passed to it.
{
switch(x)
{
case 0x00 : return '0';
break;
case 0x01 : return '1';
break;
case 0x02 : return '2';
break;
case 0x03 : return '3';
break;
case 0x04 : return '4';
break;
case 0x05 : return '5';
break;
case 0x06 : return '6';
break;
case 0x07 : return '7';
break;
case 0x08 : return '8';
break;
case 0x09 : return '9';
break;
case 0x0A : return 'A';
break;
case 0x0B : return 'B';
break;
case 0x0C : return 'C';
break;
case 0x0D : return 'D';
break;
case 0x0E : return 'E';
break;
case 0x0F : return 'F';
break;
}
return 0x00;
}
char fromASCIICode(char x) //This function takes the ASCII Code of the Symbol used to represent a Hexadecimal Digit and returns the Hexadecimal Digit itself.
{
switch(x)
{
case '0' : return 0x00;
break;
case '1' : return 0x01;
break;
case '2' : return 0x02;
break;
case '3' : return 0x03;
break;
case '4' : return 0x04;
break;
case '5' : return 0x05;
break;
case '6' : return 0x06;
break;
case '7' : return 0x07;
break;
case '8' : return 0x08;
break;
case '9' : return 0x09;
break;
case 'A' : return 0x0A;
break;
case 'B' : return 0x0B;
break;
case 'C' : return 0x0C;
break;
case 'D' : return 0x0D;
break;
case 'E' : return 0x0E;
break;
case 'F' : return 0x0F;
break;
}
return 0x00;
}
void main()
{
int i; //General purpose loop counter variable.
Nr=128; //The length of key: 128-bits. (The possible values allowed by AES are 128, 192 or 256 only)
Nk = Nr / 32; //Calculate Nk and Nr from the
Nr = Nk + 6; // "length of the key" value.
uart_init(); //Initialize the UART
LCD_init(); //Initialize the LCD
//Get the plaintext from UART
uart_puts("\r\n\r\nEnter the Cipher using ASCII Symbols for Hex digits:\n");
for(i=0;i<Nk*4;i++)
{
in[i]=fromASCIICode(uart_getc())<<4;
in[i]+=fromASCIICode(uart_getc());
}
KeyExpansion(); //The KeyExpansion routine must be called before encryption.
InvCipher(); //The next function call encrypts the PlainText with the Key using AES algorithm.
//Report all Strings (PLAINTEXT,KEY,CIPHER) to UART --->
//Send Cipher to UART
uart_puts("\r\n\r\nCipher entered (Hex Digits) :\n");
for(i=0;i<Nk*4;i++)
{
uart_putc(toASCIICode(in[i]>>4)); //Send Most Significant Nibble to UART
uart_putc(toASCIICode(in[i]&0x0F)); //Send Least Significant Nibble to UART
}
uart_puts("\r\nCipher entered (String) :\n");
for(i=0;i<Nk*4;i++)
{
uart_putc(in[i]);
}
//Send Key to UART
uart_puts("\r\n\r\nKey (Hex Digits) :\n");
for(i=0;i<Nk*4;i++)
{
uart_putc(toASCIICode(Key[i]>>4)); //Send Most Significant Nibble to UART
uart_putc(toASCIICode(Key[i]&0x0F)); //Send Least Significant Nibble to UART
}
uart_puts("\r\nKey (String) :\n");
for(i=0;i<Nk*4;i++)
{
uart_putc(Key[i]);
}
//Send plaintext to UART
uart_puts("\r\n\r\nPlaintext after decryption (Hex Digits) :\n");
for(i=0;i<Nk*4;i++)
{
uart_putc(toASCIICode(out[i]>>4)); //Send Most Significant Nibble to UART
uart_putc(toASCIICode(out[i]&0x0F)); //Send Least Significant Nibble to UART
}
uart_puts("\r\nPlaintext after decryption (String) :\n");
for(i=0;i<Nk*4;i++)
{
uart_putc(out[i]);
}
//<--- Report all Strings (PLAINTEXT,KEY,CIPHER) to UART
//Show the plaintext on LCD
LCD_row1();
for(i=0;i<Nk*4;i++)
{
LCD_putc(out[i]); //Send Most Significant Nibble to LCD
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -