Tải bản đầy đủ (.docx) (20 trang)

Chương trình C/C++ Mã hóa và giải mã thuật toán AES bằng Sbox động

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (232.98 KB, 20 trang )

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



×