Mục lục
1. Chức năng chương trình.........................................................................1
2. Cấu trúc chương trình.............................................................................1
Sbox.h.........................................................................................................2
Sbox.cpp.....................................................................................................2
AES.cpp......................................................................................................6
Test.txt......................................................................................................19
1. Chức năng chương trình
Chương trình gồm 3 chức năng chính:
- Tạo Sbox động bằng sự thay đổi của đa thức bất khả quy
- Mã hóa bản rõ bằng thuật tốn AES với khóa: 128, 192 và 256 bit
- Giải mã bằng thuật tốn AES với khóa: 128, 192 và 256 bit
** Mã hóa và giải mã AES sử dụng Sbox động được tạo từ chức năng 1
thay vì Sbox tĩnh thường dùng để nâng cao độ an tồn của thuật tốn.
1. Cấu trúc chương trình
- Sbox.h: Thư viện định nghĩa các hàm của file Sbox.cpp
- Sbox.cpp: Viết các hàm menu, hàm kiểm tra đầu vào, hàm tạo sbox
động.
- AES.cpp: Bao gồm hàm mã hóa và giải mã AES
- Test.txt: Bao gồm 1 ví dụ về khóa 128, 192, 256 bit và bản rõ để chạy
chương trình
1
************************ Mã nguồn C/C++********************
Sbox.h
#include <cstdio>
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <io.h>
#include <direct.h>
#include <iostream>
#include <time.h>
typedef unsigned char uc;
void initialize(short irrPol,uc sbox[16*16]);
uc msb(unsigned short num);
uc divide(unsigned short a, uc b, uc &r);
uc multiply(uc a, uc b);
uc inverse(uc b,short irrPol);
uc map (uc a);
int s_box_gen(short irrPol,uc sbox[16*16]);
void inv_s_box_gen(uc sbox[16*16],uc invsbox[16*16]);
int generate_sbox(uc Key[], uc sbox[16*16], int Key_len);
void menu();
int chon();
int checkinput(char input[]);
int checkkey(char input[]);
Sbox.cpp
#include "sbox.h"
// Khởi tạo Sbox
void initialize(short irrPol, uc sbox[16 * 16])
{
uc i, j;
for (i = 0; i <= 0xF; i++)
{
for (j = 0; j <= 0xF; j++)
{
sbox[i * 16 + j] = inverse((i << 4) + j, irrPol); // tìm giá trị nghịch
đảo của input
}
}
}
// Trả vềvị trí cao nhấ
t có giá trị khác 0
uc msb(unsigned short num)
{
uc i;
for (i = 0; i <= 8; i++)
{
if (!(num >> (i + 1)))
2
{
return i;
}
}
return 0;
}
// Thực hiện phép chia
uc divide(unsigned short a, uc b, uc &r)
{
uc a_msb = msb(a);
uc b_msb = msb(b);
if (a < b)
{
r = a;
return 0;
}
uc bit = a_msb - b_msb;
unsigned short temp = b;
temp = temp << bit;
a = a ^ temp;
return (1 << bit) | divide(a, b, r);
}
// Thực hiện nhân đa thức trong trường GF(2)
uc multiply(uc a, uc b,uc irrPol)
{
uc res = 0;
if (b & 0x01)
{
res = a;
}
for (uc i = 1; i < 8; i++)
{
if (b & (0x01 << i))
{
uc temp = a;
for (uc j = 0; j < i; j++)
{
if (!(temp & 0x80))
{
temp <<= 1;
}
else
{
temp <<= 1;
temp = temp ^ irrPol;
}
}
res = res ^ temp;
}
}
return res;
}
// Tìm phép nhân nghịch đảo với đa thức bấ
t khả quy, xây dựng bảng phụ trợ
uc inverse(uc b, short irrPol)
{
if (b == 0)
return 0; // Nghịch đảo của 0 bằng 0
short r0 = irrPol; // đặt r0 = đa thức bấ
t khả quy
uc r1 = b, r2, q;
uc w0 = 0, w1 = 1, w2; // cột phụ trợ
3
q = divide(r0, r1, r2); // thương của đa 2 đa thức
w2 = w0 ^ multiply(q, w1,irrPol); // cột phụ trợ
while (1)
{
if (r2 == 0)
break;
r0 = r1;
r1 = r2;
q = divide(r0, r1, r2);
w0 = w1;
w1 = w2;
w2 = w0 ^ multiply(q, w1,irrPol);
}
return w1;
}
// Phép biế
n đổ
i Affine:
uc map(uc a)
{
uc c = 0x63; // hằng sốaffine
uc res = 0x0;
uc temp = 0x0;
uc i;
for (i = 0; i < 8; i++)
{
temp = temp ^ ((a >> i) & 0x1) ^ ((a >> ((i + 4) % 8)) & 0x1);
temp = temp ^ ((a >> ((i + 5) % 8)) & 0x1) ^ ((a >> ((i + 6) % 8)) & 0x1);
temp = temp ^ ((a >> ((i + 7) % 8)) & 0x1) ^ ((c >> i) & 0x1);
res = res | (temp << i);
temp = 0x0;
}
return res;
}
// Hàm tạo S-box phụ thuộc đa thức bấ
t khả quy
int s_box_gen(short irrPol, uc sbox[16 * 16])
{ FILE *f;
f = fopen("Sbox.txt", "wb");
printf("\n\t\t\tIrrPol: 0x%2X \n", irrPol);
fprintf(f,"irreducible polynomial: 0x%2X", irrPol);
fprintf(f, "\n SBox[16*16] = {\n");
initialize(irrPol, sbox); // Khởi tạo và thực hiện tìm nghịch đảo nhân
for ( uc i = 0; i <= 0xF; i++)
{ for (uc j = 0; j <= 0xF; j++)
{sbox[i * 16 + j] = map(sbox[i * 16 + j]);//Phép biế
n đổ
i Affine
fprintf(f, " %02X ", sbox[i * 16 + j]);}
fprintf(f, "\n");}
fprintf(f, "};");
fclose(f);
return 0;
}
//Hàm tạo S-box nghịch đảo
void inv_s_box_gen(uc sbox[16 * 16], uc invsbox[16 * 16])
{
FILE *f;
for (uc i = 0; i < 16; i++)
for (int j = 0; j < 16; j++)
{
unsigned char t;
uc x, y;
t = sbox[i * 16 + j];
x = t >> 4;
y = t & 0x0f;
4
invsbox[x * 16 + y] = (unsigned char)((i << 4) + j);
}
f = fopen("invSbox.txt", "wb");
fprintf(f, "Hop the hoan vi nguoc: ");
fprintf(f, "\n invSBox[16*16] = {\n");
for (int i = 0; i < 16; i++)
{
for (int j = 0; j < 16; j++)
{
fprintf(f, " %02X ", invsbox[i * 16 + j]);
}
fprintf(f, "\n");
}
fprintf(f, "};");
fclose(f);
}
// Hàm tạo S-box phụ thuộc khóa dựa trên việc thay đổ
i đa thức bấ
t khả quy
int generate_sbox(uc Key[65], uc sbox[16 * 16], int key_len)
{
uc i, j;
short irr[] = {0x11B, 0x11D, 0x12B, 0x12D, 0x139, 0x13F, 0x14D, 0x15F, 0x163,
0x165,
0x169, 0x171, 0x177, 0x17B, 0x187, 0x18B, 0x18D, 0x19F, 0x1A3,
0x1A9, 0x1B1,
0x1BD, 0x1C3, 0x1CF, 0x1D7, 0x1DD, 0x1E7, 0x1F3, 0X1F5, 0x1F9};
int y = 0;
for (i = 0; i < key_len; i++)
{
y = y ^ Key[i];
}
int t = y % 0x1e;
short irrPol = irr[t];
s_box_gen(irrPol, sbox);
return 0;
}
void menu()
{
printf("\n\n\t\t=============== Chuong trinh thuc nghiem ===============\n");
printf("\t\t*** 1. Tao S-box phu thuoc khoa\t\t ***\n");
printf("\t\t*** 2. Ma hoa AES \t\t\t\t ***\n");
printf("\t\t*** 3. Giai ma AES \t\t\t\t ***\n");
printf("\t\t*** 4. Dung chuong trinh \t\t\t ***\n");
printf("\t\t========================================================\n\n");
}
// Chon menu
int chon()
{
menu();
int n;
printf("\t\t\tChon chuc nang:");
scanf("%d", &n);
if ((n == 1) || (n == 2) || (n == 3) || (n == 4))
{
return n;
}
else
{
printf("Lua chon khong hop le! \n");
getchar();
return chon();
}
5
}
// Kiể
m tra điề
u kiện input: Độ dài 128 bit + hệ thập lục phân
int checkinput(char input[])
{
fflush(stdin);
fgets(input, 50, stdin);
input[strcspn(input, "\n")] = 0;
uc str_len = strlen(input);
printf ("str_len:%s",str_len);
if (str_len != 32) // Key co do dai 16 byte
{
return 1;
getchar();
}
else
{
int count;
for (int i = 0; i < str_len ; i++)
{
if (isxdigit(input[i]) == 0)
{
count++;
}
}
if (count == 0)
return str_len/2;
else
return 1;
}
}
// Kiể
m tra điề
u kiện khóa: Độ dài khóa + là hệ thập lục phân
int checkkey(char key[])
{
fflush(stdin);
fgets(key, 100, stdin);
key[strcspn(key, "\n")] = 0;
uc str_len = strlen(key);
if ((str_len != 32) && (str_len != 48) && (str_len != 64))
{
return 1;
getchar();
}
else
{
int count;
for (int i = 0; i < str_len ; i++)
{
if (isxdigit(key[i]) == 0)
{
count++;
}
}
if (count == 0)
{
return str_len/2;
}
else
return 1;
}
}
6
AES.cpp
#include "sbox.h"
#include <stdio.h>
typedef unsigned char uc;
uc sbox[16 * 16];
uc invsbox[16 * 16];
int Nk,Nr;
unsigned char state[4 * 4]; /* 128 bit */
unsigned char w[4 * (14 + 1) * 4]; /* max */
unsigned char Rcon[11 * 4] = {
0x00, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00,
0x04, 0x00, 0x00, 0x00,
0x08, 0x00, 0x00, 0x00,
0x10, 0x00, 0x00, 0x00,
0x20, 0x00, 0x00, 0x00,
0x40, 0x00, 0x00, 0x00,
0x80, 0x00, 0x00, 0x00,
0x1b, 0x00, 0x00, 0x00,
0x36, 0x00, 0x00, 0x00};
// Phep nhan tren truong GF(2^8)
/* Thuc hien phep nhan 0x02 * a */
unsigned char gfMultBy02(unsigned char i)
{
if (i < 0x80)
i = i << 1;
else
{
i = i << 1;
i = (unsigned char)((int)i ^ (int)0x1b);
}
return i;
}
/* Thuc hien phep nhan 0x03 * a */
unsigned char gfMultBy03(unsigned char i)
{
return (unsigned char)((int)gfMultBy02(i) ^ (int)i);
}
unsigned char gfMultBy09(unsigned char i)
{
return (unsigned char)((int)gfMultBy02(gfMultBy02(gfMultBy02(i))) ^ (int)i);
}
unsigned char gfMultBy0b(unsigned char i)
{
return (unsigned char)((int)gfMultBy02(gfMultBy02(gfMultBy02(i))) ^
(int)gfMultBy02(i) ^ (int)i);
}
unsigned char gfMultBy0d(unsigned char i)
{
return (unsigned char)((int)gfMultBy02(gfMultBy02(gfMultBy02(i))) ^
(int)gfMultBy02(gfMultBy02(i)) ^ (int)(i));
}
unsigned char gfMultBy0e(unsigned char i)
7
{
return (unsigned char)((int)gfMultBy02(gfMultBy02(gfMultBy02(i))) ^
(int)gfMultBy02(gfMultBy02(i)) ^ (int)gfMultBy02(i));
}
// Dich vong trai di 1 Byte
unsigned long RotWord(unsigned long t)
{
unsigned char *p;
unsigned char temp;
p = (unsigned char *)&t;
temp = *p;
*p = *(p + 1);
p++;
*p = *(p + 1);
p++;
*p = *(p + 1);
p++;
*p = temp;
return t;
}
// Dich trai cac dong (hang)
void ShiftRows(void)
{
unsigned char temp[4 * 4];
for (int i = 1; i < 4; i++)
for (int j = 0; j < 4; j++)
{
temp[i * 4 + j] = state[i * 4 + j];
}
/* Vi dong 0 khong dich vong. Dong thu i dich di i byte */
for (int i = 1; i < 4; i++)
for (int j = 0; j < 4; j++)
{
state[i * 4 + j] = temp[i * 4 + ((i + j) % 4)];
}
}
// Thay the mang 4*4 State thanh mang 4*4 qua Sbox.
void SubBytes(void)
{
int x, y;
for (int i = 0; i < 4; i++) /* cot */
for (int j = 0; j < 4; j++) /* hang */
{
state[i * 4 + j] = sbox[state[i * 4 + j]];
}
}
// Thay the qua Sbox. Thay the 4 byte. Dung trong luoc do tao khoa.
unsigned long SubWord(unsigned long t)
{
unsigned char *p;
int x, y;
p = (unsigned char *)&t;
x = (unsigned char)((int)(*p) >> 4);
y = (unsigned char)((int)(*p) & 0x0f);
*p = sbox[x * 16 + y];
p++;
x = (unsigned char)((int)(*p) >> 4);
y = (unsigned char)((int)(*p) & 0x0f);
*p = sbox[x * 16 + y];
p++;
x = (unsigned char)((int)(*p) >> 4);
8
y = (unsigned char)((int)(*p) & 0x0f);
*p = sbox[x * 16 + y];
p++;
x = (unsigned char)((int)(*p) >> 4);
y = (unsigned char)((int)(*p) & 0x0f);
*p = sbox[x * 16 + y];
return t;
}
void KeyExpantion(unsigned char *key, unsigned char *w)
{
/* Nk*4 byte dau duoc lay tu khoa vao -> duoc Nk dong */
for (int i = 0; i < Nk; i++)
{ /* theo dong */
w[i * 4] = key[i * 4];
w[i * 4 + 1] = key[i * 4 + 1];
w[i * 4 + 2] = key[i * 4 + 2];
w[i * 4 + 3] = key[i * 4 + 3];
}
/* Tu dong thu Nk den 4*(Nr+1)*4 */
for (int row = Nk; row < (4 * (Nr + 1)); row++)
{
unsigned long temp = *((unsigned long *)&w[(row - 1) * 4]); /* W[i-1] =
w[4*(i-1)]*/
if (row % Nk == 0)
{
temp = SubWord(RotWord(temp)) ^ (*((unsigned long *)&Rcon[(row / Nk) *
11]));
}
else if (Nk > 6 && (row % Nk == 4))
{
temp = SubWord(temp);
}
temp = temp ^ (*((unsigned long *)(&w[(row - Nk) * 4])));
/* Ghi lai 4 byte nay vao w ung voi dong khoa thu row*/
*((unsigned long *)&w[row * 4]) = temp;
}
}
/* Cong State voi khoa vong thu round */
void AddRoundKey(int round)
{
for (int i = 0; i < 4; i++) /* cot */
for (int j = 0; j < 4; j++) /* hang */
{
state[i * 4 + j] = (unsigned char)((int)state[i * 4 + j] ^ (int)w[(round *
4 + j) * 4 + i]);
}
}
/* MixColumns */
void MixColumns(void)
{
unsigned char temp[4 * 4];
/* Copy du lieu tu State vao temp */
for (int i = 0; i < 4; i++)
for (int j = 0; j < 4; j++)
{
temp[i * 4 + j] = state[i * 4 + j];
}
for (int i = 0; i < 4; i++)
{
/* Nhan cot thu i voi da thuc
c(x) = '03h'x^3 + '01h'x^2 + '01h'x + '02h'
9
*/
/* b'[0] = 02*b[0] + 03*b[1] + b[2] + b[3] */
state[0 * 4 + i] = (unsigned char)((int)gfMultBy02(temp[0
(int)gfMultBy03(temp[1
(int)temp[2 * 4 + i] ^
(int)temp[3 * 4 + i]);
/* b'[1] = b[0] + 02*b[1] + 03*b[2] + b[3] */
state[1 * 4 + i] = (unsigned char)((int)temp[0 * 4 + i] ^
(int)gfMultBy02(temp[1
(int)gfMultBy03(temp[2
(int)temp[3 * 4 + i]);
/* b'[2] = b[0] + b[1] + 02*b[2] + 03*b[3] */
state[2 * 4 + i] = (unsigned char)((int)temp[0 * 4 + i] ^
(int)temp[1 * 4 + i] ^
(int)gfMultBy02(temp[2
(int)gfMultBy03(temp[3
/* b'[3] = 03*b[0] + b[1] + 01*b[2] + 02*b[3] */
state[3 * 4 + i] = (unsigned char)((int)gfMultBy03(temp[0
(int)temp[1 * 4 + i] ^
(int)temp[2 * 4 + i] ^
(int)gfMultBy02(temp[3
}
}
void AES_Cipher(unsigned char *input, unsigned char *output)
{
/* 0. Neu khong co du lieu vao -> THOAT */
if ((input == NULL) || (output == NULL))
return;
/* 1. Dua input vao State */
for (int i = 0; i < 16; i++)
{ /* theo cot truoc */
state[(i % 4) * 4 + (i / 4)] = input[i];
}
AddRoundKey(0);
/* 3. Thuc hien Nr vong lap */
for (int round = 1; round <= (Nr - 1); ++round)
{
SubBytes();
ShiftRows();
MixColumns();
AddRoundKey(round);
}
/* 4. Final Round */
SubBytes();
ShiftRows();
AddRoundKey(Nr);
/* Lay du lieu ra */
for (int i = 0; i < 16; i++)
{ /* lay theo cot */
output[i] = state[(i % 4) * 4 + (i / 4)];
}
}
/* Cac ham phuc vu qua trinh giai ma */
/* Dich vong sang phai 1 byte */
void InvShiftRows(void)
{
unsigned char temp[4 * 4];
for (int i = 1; i < 4; i++)
for (int j = 0; j < 4; j++)
10
* 4 + i]) ^
* 4 + i]) ^
* 4 + i]) ^
* 4 + i]) ^
* 4 + i]) ^
* 4 + i]));
* 4 + i]) ^
* 4 + i]));
{
temp[i * 4 + j] = state[i * 4 + j];
}
/* lay nguoc cua phep bien doi o ShiftRows o tren */
for (int i = 1; i < 4; i++)
for (int j = 0; j < 4; j++)
{
state[i * 4 + ((i + j) % 4)] = temp[i * 4 + j];
}
}
/* Thuc hien phep the nguoc - thong qua bang the nguoc invSBox */
void InvSubBytes(uc invsbox1[16 * 16])
{
int x, y;
for (int i = 0; i < 4; i++)
for (int j = 0; j < 4; j++)
{
// x= (unsigned char)((int)(state[i*4+j])>>4);
// y= (unsigned char)((int)(state[i*4+j])&0x0f);
state[i * 4 + j] = invsbox1[state[i * 4 + j]];
}
}
void InvMixColumns(void)
{
unsigned char temp[4 * 4];
for (int i = 0; i < 4; i++)
for (int j = 0; j < 4; j++)
{
temp[i * 4 + j] = state[i * 4 + j];
}
for (int i = 0; i < 4; i++)
{
/* Nhan cot thu i voi da thuc
d(x) = '0bh'x^3 + '0dh'x^2 + '09h'x + '0eh'
*/
/* b'[0] = 0e*b[0] + 0b*b[1] + 0d*b[2] + 09*b[3] */
state[0 * 4 + i] = (unsigned char)((int)gfMultBy0e(temp[0 * 4 + i]) ^
(int)gfMultBy0b(temp[1 * 4 + i]) ^
(int)gfMultBy0d(temp[2 * 4 + i]) ^
(int)gfMultBy09(temp[3 * 4 + i]));
/* b'[1] = 09*b[0] + 0e*b[1] + 0b*b[2] + 0d*b[3] */
state[1 * 4 + i] = (unsigned char)((int)gfMultBy09(temp[0 * 4 + i]) ^
(int)gfMultBy0e(temp[1 * 4 + i]) ^
(int)gfMultBy0b(temp[2 * 4 + i]) ^
(int)gfMultBy0d(temp[3 * 4 + i]));
/* b'[2] = 0d*b[0] + 09*b[1] + 0e*b[2] + 0b*b[3] */
state[2 * 4 + i] = (unsigned char)((int)gfMultBy0d(temp[0 * 4 + i]) ^
(int)gfMultBy09(temp[1 * 4 + i]) ^
(int)gfMultBy0e(temp[2 * 4 + i]) ^
(int)gfMultBy0b(temp[3 * 4 + i]));
/* b'[3] = 0b*b[0] + 0d*b[1] + 09*b[2] + 0e*b[3] */
state[3 * 4 + i] = (unsigned char)((int)gfMultBy0b(temp[0 * 4 + i]) ^
(int)gfMultBy0d(temp[1 * 4 + i]) ^
(int)gfMultBy09(temp[2 * 4 + i]) ^
(int)gfMultBy0e(temp[3 * 4 + i]));
}
}
// Ham thuc hien giai ma AES
void InvAES_Cipher(unsigned char *input, unsigned char *output, uc invsbox1[16 * 16])
{
/* Neu input hoac output chua khoi tao -> THOAT */
11
if (input == NULL || output == NULL)
return;
/* 1. Dua input vao State */
for (int i = 0; i < 16; i++)
{ /* theo cot */
state[(i % 4) * 4 + (i / 4)] = input[i];
}
/* 2. AddRoundKey - Khoa cua vong thu Nr*/
AddRoundKey(Nr);
/* 3. Thuc hien Nr vong lap nguoc */
for (int round = Nr - 1; round >= 1; --round)
{
InvShiftRows();
InvSubBytes(invsbox1);
AddRoundKey(round);
InvMixColumns();
}
/* 4. Final Round */
InvShiftRows();
InvSubBytes(invsbox);
AddRoundKey(0);
/* Lay du lieu ra - theo cot*/
for (int i = 0; i < 16; i++)
{
output[i] = state[(i % 4) * 4 + (i / 4)];
}
}
void SetNkNr(int key_len) {
if (key_len == 16){
Nk = 4;
Nr = 10;
printf ("\n\t\t\t----------------- AES-128 --------------");
}
else if (key_len == 24){
Nk = 6;
Nr = 12;
printf ("\n\t\t\t----------------- AES-192 --------------");
}
else if (key_len == 32){
Nk = 8;
Nr = 14;
printf ("\n\t\t\t----------------- AES-256 --------------");
}
}
//-----------------------------Chương trình thực nghiệm----------------------------//
// Chức năng 1: Tạo S-box động phụ thuộc khóa dựa trên sự biế
n đổ
i đa thức bấ
t khả quy
void genSbox()
{
uc sbox[16 * 16],Key[16];
char Key_str[65];
int i;
printf("\t\t\tNhap Khoa: ");
int key_len = checkkey(Key_str);
if (key_len != 1)
{
for (i = 0; i < key_len; i++)
{
sscanf(Key_str + 2 * i, "%02x", &Key[i]);
}
generate_sbox(Key,sbox,key_len);// Tạo S-box phụ thuộc khóa
printf("\t\t\tSbox da duoc tao!");
12
}
else printf("\t\t\tKhoa sai dinh dang! : %d", key_len);
}
// Chức năng 2: Áp dụng thuật toán tạo S-box động vào mã hóa AES
int mahoa()
{
unsigned char bro[16], bma[16], khoa[32];
char Plantext_str[50], Key_str[100];
int i;
clock_t start, finish;
double duration;
// Nhap khoa
printf("\t\t\tNhap ban ro: ");
if (checkinput(Plantext_str) != 1)
{
for (i = 0; i < (16); i++)
{
sscanf(Plantext_str + 2 * i, "%02x", &bro[i]);
}
printf("\t\t\tNhap khoa : ");
int key_len = checkkey(Key_str);
if (key_len != 1)
{
SetNkNr(key_len);
for (i = 0; i < key_len; i++)
{
sscanf(Key_str + 2 * i, "%02x", &khoa[i]);
}
printf("\n\t\t\tBan ro: ");
for (int i = 0; i < 16; i++)
printf("%02X", bro[i]);
printf("\n\t\t\tKhoa : ");
for (int i = 0; i < key_len; i++)
printf("%02X", khoa[i]);
/*----- Qúa trình mã hóa sửdụng S-box động-----*/
start = clock();
/* 1. Thiế
t lập S-box động phụ thuộc khóa chính */
generate_sbox(khoa, sbox,key_len);
/* 2. Thiế
t lập khóa phụ*/
KeyExpantion(khoa, w);
/* 3. Gọi hàm mã hóa */
AES_Cipher(bro, bma);
/* 4. In kế
t quả */
printf("\n\t\t\tBan ma: ");
for (int i = 0; i < 16; i++)
printf("%02X", bma[i]);
finish = clock();
duration = (double)(finish - start) / CLOCKS_PER_SEC;
printf("\n\t\t\tToc do ma hoa: %f Kbits/seconds", ((float)250000) /
duration);
}
else
{
printf ("\n\t\t\tKhoa sai dinh dang!\n");
system("pause");
}
}
else
{
printf ("\n\t\t\tBan ro sai dinh dang!\n");
13
system("pause");
}
return 0;
}
// Chức năng 3: Áp dụng thuật toán vào giải mã AES
int giaima()
{
unsigned char bma[16], bdich[16], khoa[32];
char Cipher_str[100], Key_str[100];
int i;
clock_t start, finish;
double duration;
// Nhap khoa
printf("\t\t\tNhap ban ma: ");
if (checkinput(Cipher_str) != 1)
{
for (i = 0; i < 16; i++)
{
sscanf(Cipher_str + 2 * i, "%02x", &bma[i]);
}
printf("\t\t\tNhap khoa : ");
int key_len = checkkey(Key_str);
if (key_len != 1)
{
SetNkNr(key_len);
for (i = 0; i < key_len; i++)
{
sscanf(Key_str + 2 * i, "%02x", &khoa[i]);
}
printf("\n\t\t\tBan ma: ");
for (int i = 0; i < 16; i++)
printf("%02X", bma[i]);
printf("\n\t\t\tKhoa : ");
for (int i = 0; i < key_len; i++)
printf("%02X", khoa[i]);
/*----- Qúa trình giải mã sửdụng S-box động-----*/
start = clock();
/* 1. Tạo bảng hốn vị ngược phụ thuộc khóa chính */
generate_sbox(khoa, sbox, key_len);
inv_s_box_gen(sbox, invsbox);
/* 2. Thiế
t lập khóa con */
KeyExpantion(khoa, w);
/* 3. Gọi hàm giải mã */
InvAES_Cipher(bma, bdich, invsbox);
/* 4. In kế
t quả */
printf("\n\t\t\tBan dich: ");
for (int i = 0; i < 16; i++)
printf("%02X", bdich[i]);
finish = clock();
duration = (double)(finish - start) / CLOCKS_PER_SEC;
printf("\n\t\t\tToc do giai ma: %f Kbits/seconds", ((float)250000) /
duration);
}
else
{
printf ("\n\t\t\tKhoa sai dinh dang!\n");
system("pause");
}
}
14
else
{
printf ("\n\t\t\tBan ma sai dinh dang!\n");
system("pause");
}
return 0;
}
void initialize(short irrPol, uc sbox[16 * 16])
{
uc i, j;
for (i = 0; i <= 0xF; i++)
{
for (j = 0; j <= 0xF; j++)
{
sbox[i * 16 + j] = inverse((i << 4) + j, irrPol); // tìm giá trị nghịch
đảo của input
}
}
}
// Trả vềvị trí cao nhấ
t có giá trị khác 0
uc msb(unsigned short num)
{
uc i;
for (i = 0; i <= 8; i++)
{
if (!(num >> (i + 1)))
{
return i;
}
}
return 0;
}
// Thực hiện phép chia
uc divide(unsigned short a, uc b, uc &r)
{
uc a_msb = msb(a);
uc b_msb = msb(b);
if (a < b)
{
r = a;
return 0;
}
uc bit = a_msb - b_msb;
unsigned short temp = b;
temp = temp << bit;
a = a ^ temp;
return (1 << bit) | divide(a, b, r);
}
// Thực hiện nhân đa thức trong trường GF(2)
uc multiply(uc a, uc b,uc irrPol)
{
uc res = 0;
if (b & 0x01)
{
res = a;
}
for (uc i = 1; i < 8; i++)
{
if (b & (0x01 << i))
{
15
uc temp = a;
for (uc j = 0; j < i; j++)
{
if (!(temp & 0x80))
{
temp <<= 1;
}
else
{
temp <<= 1;
temp = temp ^ irrPol;
}
}
res = res ^ temp;
}
}
return res;
}
// Tìm phép nhân nghịch đảo với đa thức bấ
t khả quy, xây dựng bảng phụ trợ
uc inverse(uc b, short irrPol)
{
if (b == 0)
return 0; // Nghịch đảo của 0 bằng 0
short r0 = irrPol; // đặt r0 = đa thức bấ
t khả quy
uc r1 = b, r2, q;
uc w0 = 0, w1 = 1, w2; // cột phụ trợ
q = divide(r0, r1, r2); // thương của đa 2 đa thức
w2 = w0 ^ multiply(q, w1,irrPol); // cột phụ trợ
while (1)
{
if (r2 == 0)
break;
r0 = r1;
r1 = r2;
q = divide(r0, r1, r2);
w0 = w1;
w1 = w2;
w2 = w0 ^ multiply(q, w1,irrPol);
}
return w1;
}
// Phép biế
n đổ
i Affine:
uc map(uc a)
{
uc c = 0x63; // hằng sốaffine
uc res = 0x0;
uc temp = 0x0;
uc i;
for (i = 0; i < 8; i++)
{
temp = temp ^ ((a >> i) & 0x1) ^ ((a >> ((i + 4) % 8)) & 0x1);
temp = temp ^ ((a >> ((i + 5) % 8)) & 0x1) ^ ((a >> ((i + 6) % 8)) & 0x1);
temp = temp ^ ((a >> ((i + 7) % 8)) & 0x1) ^ ((c >> i) & 0x1);
res = res | (temp << i);
temp = 0x0;
}
return res;
}
// Hàm tạo S-box phụ thuộc đa thức bấ
t khả quy
int s_box_gen(short irrPol, uc sbox[16 * 16])
{ FILE *f;
16
f = fopen("Sbox.txt", "wb");
printf("\n\t\t\tIrrPol: 0x%2X \n", irrPol);
fprintf(f,"irreducible polynomial: 0x%2X", irrPol);
fprintf(f, "\n SBox[16*16] = {\n");
initialize(irrPol, sbox); // Khởi tạo và thực hiện tìm nghịch đảo nhân
for ( uc i = 0; i <= 0xF; i++)
{ for (uc j = 0; j <= 0xF; j++)
{sbox[i * 16 + j] = map(sbox[i * 16 + j]);//Phép biế
n đổ
i Affine
fprintf(f, " %02X ", sbox[i * 16 + j]);}
fprintf(f, "\n");}
fprintf(f, "};");
fclose(f);
return 0;
}
//Hàm tạo S-box nghịch đảo
void inv_s_box_gen(uc sbox[16 * 16], uc invsbox[16 * 16])
{
FILE *f;
for (uc i = 0; i < 16; i++)
for (int j = 0; j < 16; j++)
{
unsigned char t;
uc x, y;
t = sbox[i * 16 + j];
x = t >> 4;
y = t & 0x0f;
invsbox[x * 16 + y] = (unsigned char)((i << 4) + j);
}
f = fopen("invSbox.txt", "wb");
fprintf(f, "Hop the hoan vi nguoc: ");
fprintf(f, "\n invSBox[16*16] = {\n");
for (int i = 0; i < 16; i++)
{
for (int j = 0; j < 16; j++)
{
fprintf(f, " %02X ", invsbox[i * 16 + j]);
}
fprintf(f, "\n");
}
fprintf(f, "};");
fclose(f);
}
// Hàm tạo S-box phụ thuộc khóa dựa trên việc thay đổ
i đa thức bấ
t khả quy
int generate_sbox(uc Key[65], uc sbox[16 * 16], int key_len)
{
uc i, j;
short irr[] = {0x11B, 0x11D, 0x12B, 0x12D, 0x139, 0x13F, 0x14D, 0x15F, 0x163,
0x165,
0x169, 0x171, 0x177, 0x17B, 0x187, 0x18B, 0x18D, 0x19F, 0x1A3,
0x1A9, 0x1B1,
0x1BD, 0x1C3, 0x1CF, 0x1D7, 0x1DD, 0x1E7, 0x1F3, 0X1F5, 0x1F9};
int y = 0;
for (i = 0; i < key_len; i++)
{
y = y ^ Key[i];
}
int t = y % 0x1e;
short irrPol = irr[t];
s_box_gen(irrPol, sbox);
return 0;
}
17
void menu()
{
printf("\n\n\t\t=============== Chuong trinh thuc nghiem ===============\n");
printf("\t\t*** 1. Tao S-box phu thuoc khoa\t\t ***\n");
printf("\t\t*** 2. Ma hoa AES \t\t\t\t ***\n");
printf("\t\t*** 3. Giai ma AES \t\t\t\t ***\n");
printf("\t\t*** 4. Dung chuong trinh \t\t\t ***\n");
printf("\t\t========================================================\n\n");
}
// Chon menu
int chon()
{
menu();
int n;
printf("\t\t\tChon chuc nang:");
scanf("%d", &n);
if ((n == 1) || (n == 2) || (n == 3) || (n == 4))
{
return n;
}
else
{
printf("Lua chon khong hop le! \n");
getchar();
return chon();
}
}
// Kiể
m tra điề
u kiện input: Độ dài 128 bit + hệ thập lục phân
int checkinput(char input[])
{
fflush(stdin);
fgets(input, 50, stdin);
input[strcspn(input, "\n")] = 0;
uc str_len = strlen(input);
if (str_len != 32) // Key co do dai 16 byte
{
return 1;
getchar();
}
else
{
int count = 0;
for (int i = 0; i < str_len ; i++)
{
if (isxdigit(input[i]) == 0)
{
count++;
}
}
if (count == 0)
return str_len/2;
else
return 1;
}
}
// Kiể
m tra điề
u kiện khóa: Độ dài khóa + là hệ thập lục phân
int checkkey(char key[])
{
fflush(stdin);
fgets(key, 100, stdin);
key[strcspn(key, "\n")] = 0;
18
uc str_len = strlen(key);
if ((str_len != 32) && (str_len != 48) && (str_len != 64))
{
return 1;
getchar();
}
else
{
int count = 0;
for (int i = 0; i < str_len ; i++)
{
if (isxdigit(key[i]) == 0)
{
count++;
}
}
if (count == 0)
{
return str_len/2;
}
else
return 1;
}
}
// Hàm main
int main()
{
int n;
n = chon();
if (n == 1) genSbox();
if (n == 2) mahoa();
if (n == 3) giaima();
if (n == 4)
{
printf("\t\t\tDa dung chuong trinh!\n");
}
printf("\n\t\t\t");
system("pause");
return 0;
}
Test.txt
Key:
00112233445566778899AABBCCDDEEFF (128 bit)
00112233445566778899AABBCCDDEEFF1122334455667788 (192 bit)
00112233445566778899AABBCCDDEEFF00112233445566778899AA
BBCCDD1111 (256 bit)
PlainText:
000102030405060708090A0B0C0D0E0F (128 bit)
19
Chức năng chính của chương trình nằm ở hàm main trong AES.cpp
20