Материал: Практическая реализация алгоритма симметричного шифрования AES

Внимание! Если размещение файла нарушает Ваши авторские права, то обязательно сообщите нам

(fileDlg. DoModal() == IDOK)

{_save = fileDlg. GetFileName(); // Запись имени файла_save = fileDlg. GetPathName(); // Запись полного имени файла

}

}

void CCoursworkDlg: OnBnClickedButtonKey() // выбор ключа для работы программы

{

TCHAR Filter[] = _T («TXT Filters (*.txt)|*.txt||»); // фильтор для выбора формата файлов(_T(«C:\\»)); // выбор начальной директории

CFileDialog fileDlg (TRUE, 0, 0, OFN_FILEMUSTEXIST | OFN_HIDEREADONLY, Filter); // Создание окна диолога

if (fileDlg. DoModal() == IDOK)

{_key = fileDlg. GetFileName(); // Запись имени файла_key = fileDlg. GetPathName(); // Запись полного имени файла

}

(); // вызов функции для чтения ключа

}

CCoursworkDlg: OpenTxtFile() // функция чтения ключа

{(skm, 0, size);count = 0; // кол-во символов в файле

fstream t (fullfilename_key); // считывание в массив(int q = 0; q < size; q++)

{>> skm[q];

}.close();

}

CCoursworkDlg: ReadTxtFile() // функция чтения из файла

{(skl, 0, size);count = 0; // кол-во символов в файлеf (fullfilename_open); // считывание в массив(int q = 0; q < size; q++)

{>> skl[q];

}.close();

}

CCoursworkDlg: WriteTxtFile() // не пригодилось

{

}

CCoursworkDlg: CloseTxtFile() // запись конечного результата преобразований

{fout (fullfilename_save); // создаём объект класса ofstream для записи и связываем его с файлом cppstudio.txt

for (int e = 0; e < size; e++)

{<< out[e]; // запись строки в файл

}.close(); // закрываем файл

}

////////////////////////////////////////////////////////////////////////////////////////////////////////

CCoursworkDlg: OnBnClickedButtonShifr() // для шифрования

{((filename_save!= «») && (filename_open!= «») && (filename_key!= «»)) // для проверки заполнения полей

{();

}

{(L «Выберите все параметры!»);

}

}

CCoursworkDlg: OnBnClickedButtonDeshifr() // для дешифроваания

{

if ((filename_save!= «») && (filename_open!= «») && (filename_key!= «»)) // для проверки заполнения полей

{();

}

{(L «Выберите все параметры!»);

}

}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////

// Таблицы и общие функции для шифрования и дешифрования

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#define Nb 4 // Количество столбцов, содержащих состояние в AES. Это константа в AES. Значение = 4

#define xtime(x) ((x<<1) ^ (((x>>7) & 1) * 0x1b)) //Xtime - это макрос, который находит произведение{02} и аргумент для xtime по модулю{1b}Nr = 10; // Количество раундов.Nk = 4; // Число 32-битных слов в ключе.char RoundKey[240]; // Массив, в котором хранятся раундовые ключи.char Key[32]; // Ключевой вклад в Программу AESgetSBoxValue (int num) // таблица для замены при шифровании

{sbox[256] = {

// 0 1 2 3 4 5 6 7 8 9 A B C D E F

x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, // 0

xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, // 1

xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, // 2

x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, // 3

x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, // 4

x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, // 5

xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, // 6

x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, // 7

xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, // 8

x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, // 9

xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, //A

xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, //B

xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, //C

x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, //D

xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, //E

x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16}; //F

return sbox[num];

}

// Круглый массив постоянных слов, Rcon [i], содержит значения, заданные

// x для мощности (i-1), являющейся степенью x (x обозначается как {02}) в поле GF (28)

// Обратите внимание, что i начинается с 1, а не 0).

int Rcon[255] = {

x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a,

x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39,

x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8,

xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef,

xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc,

x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b,

x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3,

x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94,

x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20,

x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35,

x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f,

x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04,

x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63,

xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd,

x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb};

int getSBoxInvert (int num) // массив для обратной замены

{rsbox[256] =

{0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb

x7c, 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

x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25

x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92

x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84

x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06

xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b

x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73

x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e

x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b

xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4

x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f

x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef

xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61

x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d};rsbox[num];

}

CCoursworkDlg: KeyExpansion() // функция генерации раундовых ключей

{i, j;char temp[4], k;

// Ключ первого раунда - это сам ключ

for (i = 0; i<Nk; i++)

{[i * 4] = Key [i * 4];[i * 4 + 1] = Key [i * 4 + 1];[i * 4 + 2] = Key [i * 4 + 2]; [i * 4 + 3] = Key [i * 4 + 3];

}(i < (Nb * (Nr + 1))) // Все остальные раундовые ключи находятся из предыдущих раундов.

{(j = 0; j<4; j++)

{[j] = RoundKey[(i - 1) * 4 + j];

}(i% Nk == 0)

{= temp[0];[0] = temp[1];[1] = temp[2];[2] = temp[3];[3] = k;[0] = getSBoxValue (temp[0]);[1] = getSBoxValue (temp[1]);[2] = getSBoxValue (temp[2]);[3] = getSBoxValue (temp[3]);[0] = temp[0] ^ Rcon [i / Nk];

}if (Nk > 6 && i% Nk == 4)

{[0] = getSBoxValue (temp[0]);[1] = getSBoxValue (temp[1]);[2] = getSBoxValue (temp[2]);[3] = getSBoxValue (temp[3]);

}[i * 4 + 0] = RoundKey[(i - Nk) * 4 + 0] ^ temp[0];[i * 4 + 1] = RoundKey[(i - Nk) * 4 + 1] ^ temp[1];[i * 4 + 2] = RoundKey[(i - Nk) * 4 + 2] ^ temp[2];[i * 4 + 3] = RoundKey[(i - Nk) * 4 + 3] ^ temp[3];++;

}

}

CCoursworkDlg: AddRoundKey (int round) // функция добавления ключей

{i, j;(i = 0; i<4; i++)

{(j = 0; j<4; j++)

{[j] [i] ^= RoundKey [round * Nb * 4 + i * Nb + j];

}

}

}

////////////////////////////////////////////////////////////////////////////////////////////////////////

// ШИФРОВАНИЕ ДЛЯ 128 БИТНОГО КЛЮЧА

////////////////////////////////////////////////////////////////////////////////////////////////////////

CCoursworkDlg: DefiningInputParameters() // тело основной функции при шифровании

{i;

// Копирование ключа и простого текста

for (i = 0; i<Nk * 4; i++)

{[i] = skm[i];

in[i] = skl[i];

}

(); // Функцию генерации ключей надо вызывать до шифрования

(); // функция шифрования файла по алгоритму AES

// Вывести зашифрованный текст.();

}


void CCoursworkDlg: SubBytes() // замена исходных данных в матрице на данные из заменной таблицы

{i, j;(i = 0; i<4; i++)

{(j = 0; j<4; j++)

{[i] [j] = getSBoxValue (state[i] [j]);

}

}

}

CCoursworkDlg: ShiftRows() // сдвиг каждой строки влево на на определенное колличество байт

{char temp;

// Сдвиг первой строки на 1 столбц влево

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

// Сдвиг 2 строки на 2 влево= state[2] [0];[2] [0] = state[2] [2];[2] [2] = temp;= state[2] [1];[2] [1] = state[2] [3];[2] [3] = temp;

// Сдвиг 3 строки на 3 влево= state[3] [0];

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

}

// ^ побитовое ИЛИCCoursworkDlg: MixColumns() // Функция смешивания столбцов

{i;char Tmp, Tm, t;(i = 0; i<4; i++)

{= state[0] [i];= state[0] [i] ^ state[1] [i] ^ state[2] [i] ^ state[3] [i];= state[0] [i] ^ state[1] [i]; Tm = xtime(Tm); state[0] [i] ^= Tm ^ Tmp;= state[1] [i] ^ state[2] [i]; Tm = xtime(Tm); state[1] [i] ^= Tm ^ Tmp;= state[2] [i] ^ state[3] [i]; Tm = xtime(Tm); state[2] [i] ^= Tm ^ Tmp;= state[3] [i] ^ t; Tm = xtime(Tm); state[3] [i] ^= Tm ^ Tmp;

}

}


void CCoursworkDlg: Cipher() // основная функция шифрования

{i, j, round = 0;

(i = 0; i<4; i++) // перенос входных данных в массив для обработки

{(j = 0; j<4; j++)

{[j] [i] = in [i * 4 + j];

}

}

// Добавьте ключ первого раунда в состояние перед началом раундов

AddRoundKey(0);

(round = 1; round<Nr; round++) // цикл для выполнения првых 9 раундов

{();();();(round);

}

// функции для последнего раунда:

SubBytes();

ShiftRows();

AddRoundKey(Nr);

(i = 0; i<4; i++) // копирование результатта в массив для вывода результата

{(j = 0; j<4; j++)

{[i * 4 + j] = state[j] [i];

}

}

}

////////////////////////////////////////////////////////////////////////////////////////////////////////

// ДЕШИФРОВАНИЕ ДЛЯ 128 БИТНОГО КЛЮЧА

////////////////////////////////////////////////////////////////////////////////////////////////////////

CCoursworkDlg: Description()

{

// Копирование ключа и CipherText(int i = 0; i < Nk * 4; i++)

{[i] = skm[i];[i] = skl[i];

}


 // Процедуру Key-Expansion необходимо вызывать перед процедурой дешифрования.

KeyExpansion();

// Следующий вызов функции расшифровывает CipherText с помощью ключа, используя алгоритм AES.();

();

}

InvSubBytes() // функция обратной замены

{i, j;(i = 0; i<4; i++)

{(j = 0; j<4; j++)

{[i] [j] = getSBoxInvert (state[i] [j]);

}

}

}

InvShiftRows() // функция сдвига строк в право

{char temp;

// Поворот первой строки 1 столбца вправо

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

// Второй= state[2] [0];[2] [0] = state[2] [2];[2] [2] = temp;= state[2] [1];[2] [1] = state[2] [3];[2] [3] = temp;

// третьей= state[3] [0];[3] [0] = state[3] [1];[3] [1] = state[3] [2];[3] [2] = state[3] [3];[3] [3] = temp;

}

// Multiplty - это макрос, используемый для умножения чисел в поле 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))))))

void InvMixColumns() // функция для обратного смешифания столбцов

{i;char a, b, c, d;(i = 0; i<4; i++)

{

= state[0] [i];= state[1] [i];= state[2] [i];= state[3] [i];

[0] [i] = Multiply (a, 0x0e) ^ Multiply (b, 0x0b) ^ Multiply (c, 0x0d) ^ Multiply (d, 0x09);[1] [i] = Multiply (a, 0x09) ^ Multiply (b, 0x0e) ^ Multiply (c, 0x0b) ^ Multiply (d, 0x0d);[2] [i] = Multiply (a, 0x0d) ^ Multiply (b, 0x09) ^ Multiply (c, 0x0e) ^ Multiply (d, 0x0b);[3] [i] = Multiply (a, 0x0b) ^ Multiply (b, 0x0d) ^ Multiply (c, 0x09) ^ Multiply (d, 0x0e);

}

}

// InvCipher - основная функция дешифрования.CCoursworkDlg: InvCipher()

{i, j, round = 0;(i = 0; i<4; i++) // Копируем вход CipherText в массив состояний.

{(j = 0; j<4; j++)

{[j] [i] = in [i * 4 + j];

}

}(Nr); // добавление первого ключа(round = Nr - 1; round>0; round-)

{();();(round);();

}

// Функции для последнего раунда:

InvShiftRows();

InvSubBytes();(0);(i = 0; i<4; i++) // копирование в выходной массив

{(j = 0; j<4; j++)

{[i * 4 + j] = state[j] [i];

}

}

}