Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Болтушкин Л.С., группа 712-2, лабораторная 6.docx
Скачиваний:
0
Добавлен:
20.02.2026
Размер:
631.06 Кб
Скачать

Министерство науки и высшего образования Российской Федерации

Федеральное государственное автономное образовательное учреждение высшего образования

ТОМСКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ СИСТЕМ УПРАВЛЕНИЯ И РАДИОЭЛЕКТРОНИКИ (ТУСУР)

Кафедра комплексной информационной безопасности электронно-вычислительных систем (КИБЭВС)

ШИФРОВАНИЕ ДАННЫХ С ПОМОЩЬЮ ETOKEN

Отчет по лабораторной работе №6

по дисциплине «Программно-аппаратные средства защиты информации»

Выполнил:

Студент гр. 712-2

_______ Л.С. Болтушкин

_______ 2026

Руководитель

Преподаватель кафедры КИБЭВС

_______ С.А. Пашкевич

_______ 2026

Введение

Целью данной лабораторной работы является ознакомление с типами шифрования и механизмами, обеспечивающими генерацию ключей eToken, а также приобретение навыков шифрования и расшифрования данных с помощью eToken.

1 Ход работы

Первым делом были созданы 2 уникальных файла с инициалами и группой, которые понадобятся для шифрования и дешифрования, важным условием является то, что один файл более 128 байт, второй менее (рисунок 1.1).

Рисунок 1.1 – Создание файлов

Далее прописана функция CreateSessionKey для того, чтобы создать сессионный ключ и получить его идентификатор (рисунок 1.2).

Рисунок 1.2 – Функция CreateSessionKey

Далее реализованы функции C_EncryptInit и C_EncryptUpdate, для шифрования данных (рисунок 1.3 – 1.4). В качестве механизма используйте алгоритм шифрования CKM_DES3_CBC, переменная ckm_DES3, что видно на рисунке 1.2.

Рисунок 1.3 – Реализация шифрования, часть 1

Рисунок 1.4 – Реализация шифрования, часть 2

Для расшифрования данных были использованы функции: C_DecryptInit и C_DecryptUpdate (рисунок 1.5 – 1.6).

Рисунок 1.5 – Реализация расшифрования, часть 1

Рисунок 1.6 - Реализация расшифрования, часть 2

Далее проверена работоспособность программы на ранее созданных файлах, что представлено на рисунках 1.7 – 1.9.

Рисунок 1.7 – Успешная проверка на файле размером более 128 байт, часть 1

Рисунок 1.8 - Успешная проверка на файле размером более 128 байт, часть 2

Рисунок 1.9 - Успешная проверка на файле размером менее 128 байт

В Приложении А представлен полный листинг программы.

Заключение

В ходе выполнения данной лабораторной работы были изучены типы шифрования и механизмы, обеспечивающие генерацию ключей eToken, а также получены навыки работы с шифрованием и расшифрованием данных с помощью eToken.

Приложение а

(обязательное)

Листинга программы

#include "stdlib.h"

#include "stdio.h"

#include "include\eTPkcs11.h"

#include <windows.h>

#include <string.h>

using namespace std;

void init();

void leave(const char*);

//Глобальные переменные

CK_FUNCTION_LIST_PTR pFunctionList = NULL;

CK_C_GetFunctionList pGFL = 0;

bool wasInit = false;

void init()

{

// Загружаем dll

HINSTANCE hLib = LoadLibraryA("etpkcs11.DLL");

if (hLib == NULL)

{

leave("Cannot load DLL.");

}

// Ищем точку входа для C_GetFunctionList

(FARPROC&)pGFL = GetProcAddress(hLib, "C_GetFunctionList");

if (pGFL == NULL)

{

leave("Cannot find GetFunctionList().");

}

//Берем список функций

if (CKR_OK != pGFL(&pFunctionList))

{

leave("Can't get function list. \n");

}

// Инициализируем библиотеку PKCS#11

if (CKR_OK != pFunctionList->C_Initialize(0))

{

leave("C_Initialize failed...\n");

}

wasInit = true;

}

static void leave(const char * message)

{

if (message) printf("%s\n", message);

if (wasInit)

{

// Закрываем библиотеку PKCS#11

if (CKR_OK != pFunctionList->C_Finalize(0))

{

printf("C_Finalize failed...\n");

}

wasInit = false;

}

exit(message ? -1 : 0);

}

/* Convinience method to retrieve the first PKCS#11 slot of a connected token */

static CK_ULONG GetFirstSlotId()

{

CK_ULONG slotID = -1;

CK_ULONG ulCount = 0;

CK_SLOT_ID_PTR pSlotIDs = NULL_PTR;

CK_ULONG i;

if (pFunctionList->C_GetSlotList(TRUE, NULL_PTR, &ulCount) == CKR_OK)

{

if (ulCount > 0)

{

pSlotIDs = new CK_SLOT_ID[ulCount];

if ((pFunctionList->C_GetSlotList(TRUE, pSlotIDs, &ulCount)) == CKR_OK)

{

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

{

CK_SLOT_INFO info;

if ((pFunctionList->C_GetSlotInfo(pSlotIDs[i], &info)) == CKR_OK)

{

if (info.flags & (CKF_HW_SLOT | CKF_TOKEN_PRESENT))

{

slotID = pSlotIDs[i];

break;

}

}

}

}

}

}

if (pSlotIDs)

{

delete[] pSlotIDs;

pSlotIDs = NULL_PTR;

}

return slotID;

}

//Читаем файл в массив byte

static bool ReadDataFromFile(const char* fileName, CK_BYTE_PTR* data, DWORD* dataSize)

{

bool ret = false;

HANDLE file = CreateFileA(fileName, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);

if (file != INVALID_HANDLE_VALUE)

{

DWORD size = GetFileSize(file, NULL);

if (size != INVALID_FILE_SIZE)

{

*data = new BYTE[size];

if (ReadFile(file, *data, size, dataSize, NULL))

{

ret = true;

}

}

CloseHandle(file);

}

return ret;

}

//записываем массив в файл

static bool SaveDataToFile(const char* fileName, CK_BYTE_PTR data, DWORD dataSize)

{

bool ret = false;

HANDLE file = CreateFileA(fileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

if (file != INVALID_HANDLE_VALUE)

{

DWORD tmp = 0;

if (WriteFile(file, data, dataSize, &tmp, NULL))

{

ret = true;

}

CloseHandle(file);

}

return ret;

}

CK_OBJECT_CLASS cko_SecretKey = CKO_SECRET_KEY;

CK_KEY_TYPE ckk_DES3 = CKK_DES3;

CK_BYTE ck_False = FALSE;

CK_MECHANISM ckm_DES3_KEY_GEN = {CKM_DES3_KEY_GEN, NULL, 0};

CK_MECHANISM ckm_DES3_CBC = {CKM_DES3_CBC, NULL, 0};

#define sizeofarray(a) (sizeof(a)/sizeof(a[0]))

// Создаем сессионный ключ шифрования

CK_OBJECT_HANDLE CreateSessionKey(CK_SESSION_HANDLE hSession)

{

CK_ATTRIBUTE SessionKeyTemplate[] =

{

{ CKA_CLASS, &cko_SecretKey, sizeof(cko_SecretKey)},

{ CKA_KEY_TYPE, &ckk_DES3, sizeof(ckk_DES3)},

{ CKA_TOKEN, &ck_False, sizeof(ck_False)}

};

CK_OBJECT_HANDLE hSessionKey = NULL;

int rv = pFunctionList->C_GenerateKey(

hSession,

&ckm_DES3_KEY_GEN,

SessionKeyTemplate,

sizeofarray(SessionKeyTemplate),

&hSessionKey);

if (rv != CKR_OK) leave("Failed to create session key");

return hSessionKey;

}

int main()

{

init();

char path[100] = "D:\\file1.txt";

char pass[20];

printf("Path to file: ");

gets(path);

printf("Token PIN: ");

gets(pass);

// Находим токен

CK_ULONG slotID = GetFirstSlotId();

if (slotID == -1)

{

leave("No token is connected.");

}

// Открываем сессию

CK_SESSION_HANDLE hSession;

if (pFunctionList->C_OpenSession(slotID, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL, NULL, &hSession) != CKR_OK)

{

leave("Unable to open session with the token.");

}

// Логин

if (pFunctionList->C_Login(hSession, CKU_USER, (CK_BYTE_PTR)pass, strlen(pass)) != CKR_OK)

{

leave("Unable to login to token.");

}

CK_BYTE_PTR file = NULL;

DWORD fileSize;

// Читаем файл

if (!ReadDataFromFile(path, &file, &fileSize))

{

leave("Unable to read file.");

}

printf("File size: %d bytes\n", fileSize);

printf("Original data:\n%.*s\n\n", fileSize, file);

// 1. Создаем ключ шифрования

printf("Creating session key...\n");

CK_OBJECT_HANDLE hKey = CreateSessionKey(hSession);

printf("Session key created successfully.\n\n");

// Вычисляем размер зашифрованных данных (кратный 8 байтам для DES3)

// DES3 работает с блоками по 8 байт, но в методике указаны блоки по 128 байт

DWORD encrSize = ((fileSize + 7) / 8) * 8; // Выравнивание до ближайшего кратного 8

if (encrSize < 128) encrSize = 128; // Минимальный размер для CBC режима

CK_BYTE_PTR pEncryptedData = new BYTE[encrSize];

CK_BYTE_PTR pDecryptedData = new BYTE[encrSize];

memset(pEncryptedData, 0, encrSize);

memset(pDecryptedData, 0, encrSize);

// Устанавливаем IV (инициализационный вектор) для CBC режима

CK_BYTE iv[8] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF};

ckm_DES3_CBC.pParameter = iv;

ckm_DES3_CBC.ulParameterLen = sizeof(iv);

// 2. Шифрование данных

printf("Encrypting data...\n");

// Инициализация шифрования

CK_RV rv = pFunctionList->C_EncryptInit(hSession, &ckm_DES3_CBC, hKey);

if (rv != CKR_OK) leave("C_EncryptInit failed");

// Шифрование блоками по 128 байт

CK_ULONG bytesProcessed = 0;

CK_ULONG encryptedTotal = 0;

CK_ULONG bytesToEncrypt;

CK_ULONG encryptedPartLen;

while (bytesProcessed < fileSize)

{

// Определяем размер текущего блока (не более 128 байт)

bytesToEncrypt = (fileSize - bytesProcessed) > 128 ? 128 : (fileSize - bytesProcessed);

// Создаем буфер для текущего блока с выравниванием

CK_BYTE inputBlock[128];

memset(inputBlock, 0, 128);

memcpy(inputBlock, file + bytesProcessed, bytesToEncrypt);

// Шифруем блок

encryptedPartLen = 128;

rv = pFunctionList->C_EncryptUpdate(hSession, inputBlock, 128,

pEncryptedData + encryptedTotal, &encryptedPartLen);

if (rv != CKR_OK) leave("C_EncryptUpdate failed");

encryptedTotal += encryptedPartLen;

bytesProcessed += bytesToEncrypt;

printf("Processed %d bytes, encrypted %lu bytes\n", bytesProcessed, encryptedTotal);

}

// Завершаем шифрование

CK_ULONG lastPartLen = encrSize - encryptedTotal;

rv = pFunctionList->C_EncryptFinal(hSession, pEncryptedData + encryptedTotal, &lastPartLen);

if (rv != CKR_OK) leave("C_EncryptFinal failed");

encryptedTotal += lastPartLen;

printf("Encryption completed. Total encrypted: %lu bytes\n\n", encryptedTotal);

// Выводим зашифрованные данные в шестнадцатеричном формате

printf("Encrypted data (hex):\n");

for (DWORD i = 0; i < encryptedTotal; i++)

{

printf("%02X ", pEncryptedData[i]);

if ((i + 1) % 16 == 0) printf("\n");

}

printf("\n\n");

// 3. Расшифрование данных

printf("Decrypting data...\n");

// Инициализация расшифрования (с тем же IV)

rv = pFunctionList->C_DecryptInit(hSession, &ckm_DES3_CBC, hKey);

if (rv != CKR_OK) leave("C_DecryptInit failed");

// Расшифрование блоками по 128 байт

bytesProcessed = 0;

CK_ULONG decryptedTotal = 0;

CK_ULONG decryptedPartLen;

while (bytesProcessed < encryptedTotal)

{

// Определяем размер текущего блока (128 байт, кроме последнего)

CK_ULONG bytesToDecrypt = (encryptedTotal - bytesProcessed) > 128 ? 128 : (encryptedTotal - bytesProcessed);

decryptedPartLen = 128;

rv = pFunctionList->C_DecryptUpdate(hSession, pEncryptedData + bytesProcessed, bytesToDecrypt,

pDecryptedData + decryptedTotal, &decryptedPartLen);

if (rv != CKR_OK) leave("C_DecryptUpdate failed");

decryptedTotal += decryptedPartLen;

bytesProcessed += bytesToDecrypt;

printf("Decrypted %lu bytes\n", decryptedTotal);

}

// Завершаем расшифрование

CK_ULONG finalPartLen = encrSize - decryptedTotal;

rv = pFunctionList->C_DecryptFinal(hSession, pDecryptedData + decryptedTotal, &finalPartLen);

if (rv != CKR_OK)

{

printf("Warning: C_DecryptFinal returned 0x%08X\n", rv);

}

else

{

decryptedTotal += finalPartLen;

}

printf("Decryption completed. Total decrypted: %lu bytes\n\n", decryptedTotal);

// Выводим расшифрованные данные

printf("Decrypted data (first %d bytes):\n", fileSize);

for (DWORD i = 0; i < fileSize; i++)

{

printf("%c", pDecryptedData[i]);

}

printf("\n\n");

// Проверка результатов

if (memcmp(file, pDecryptedData, fileSize) == 0)

{

printf("SUCCESS: Decrypted data matches original!\n");

}

else

{

printf("ERROR: Decrypted data does not match original!\n");

}

// Сохраняем зашифрованные данные в файл

char encryptedFileName[120];

sprintf(encryptedFileName, "%s.enc", path);

if (SaveDataToFile(encryptedFileName, pEncryptedData, encryptedTotal))

{

printf("Encrypted data saved to %s\n", encryptedFileName);

}

// Закрываем

pFunctionList->C_Logout(hSession);

pFunctionList->C_CloseSession(hSession);

delete[] file;

delete[] pEncryptedData;

delete[] pDecryptedData;

printf("\nPress any key to exit...");

getchar();

getchar();

leave(NULL);

return 0;

}

Томск 2026