Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Разработка компонентов средств защиты информации

..pdf
Скачиваний:
10
Добавлен:
05.02.2023
Размер:
1.79 Mб
Скачать

Рисунок 1 – Импорт сертификата преподавателя

При создании сертификата используйте следующие параметры командной строки, желтым выделены параметры, которые вам нужно будет изменить:

-ic “Путь сертификата поставщика (преподавателя)”;

-ik t2 (Имя контейнера закрытого ключа поставщика (преподавателя));

-n “CN=ФИО и № группы”;

-sk “Имя контейнера с закрытым ключом”;

-pe; -ss My;

-len 1024;

“Путь к файлу создаваемого сертификата”.

Созданный сертификат будет находиться в хранилище личных сертификатов, которое можно открыть через командную строку – certmgr.msc, а также в файле по указанному вами пути.

21

Рисунок 2 – Созданный сертификат в хранилище личных сертификатов

Созданный таким образом сертификат студента будет использоваться далее для импорта на eToken.

Загрузите проект для Visual Studio под названием Lab2. В данном проекте содержится код, производящий инициализацию библиотеки PKCS#11. Добавьте заголовки функций, которые необходимо будет запрограммировать:

static void ImportCertificate(const char* fileName, const char* password);

static bool ReadCertFromFile(const char* fileName, CK_BYTE_PTR* cert, DWORD* certSize);

static void GetX509Subject(CK_BYTE_PTR cert, int certSize, CK_BYTE_PTR* subject, int* subjectSize);

static bool CreateCertFromBlob(CK_SESSION_HANDLE hSession, CK_BYTE_PTR cert, int certSize, CK_BYTE_PTR subject, int subjSize);

Здесь описаны заголовки функций, которые в дальнейшем будут использоваться для считывания и импорта сертификата. Функция

ImportCertificate(const char* fileName, const char* password) обеспечивает импорт сертификата по пути filename на eToken с ПИН-кодом password,

функция ReadCertFromFile(const char* fileName, CK_BYTE_PTR* cert, DWORD* certSize) обеспечивает чтение файла с сертификатом, функция

GetX509Subject(CK_BYTE_PTR cert, int certSize, CK_BYTE_PTR* subject, int* subjectSize) предназначена для получения темы сертификата,

функция CreateCertFromBlob(CK_SESSION_HANDLE hSession, CK_BYTE_PTR cert, int certSize, CK_BYTE_PTR subject, int subjSize)

предназначена для создания файла с сертификатом на eToken.

Добавьте в функцию main код, позволяющий считывать путь к сертификату и ПИН-код с консоли (можно использовать функцию gets(char* buffer)).

22

Объявите

следующие

переменные

в

теле

функции

ImportCertificate:

 

 

 

 

 

CK_BYTE_PTR

cert = NULL;

 

 

 

DWORD

 

 

certSize;

 

CK_BYTE_PTR

subject = NULL;

 

 

int

 

 

 

subjSize;

Функция ReadCertFromFile(const char* fileName, CK_BYTE_PTR* cert, DWORD* certSize) считывает сертификат,

расположенный по пути fileName, массив считанных данных – cert, размер считанного сертификата – certSize. Один из способов, с помощью которого в C++ можно считать файл – создание дескриптора файла с помощью функции WinAPI CreateFileA(), получение размера файла с помощью функции GetFileSize(), чтение самого файла с помощью функции ReadFile(). Найдите дополнительную информацию о данных функциях. Запрограммируйте функцию ReadCertFromFile.

Рассмотрим функцию GetX509Subject(CK_BYTE_PTR cert, int certSize, CK_BYTE_PTR* subject, int* subjectSize). Данная функция извлекает информацию о субъекте, которому принадлежит сертификат. Т.к. сертификат x.509 имеет сложную структуру (см. теоретические сведения), задача извлечения данной информации является непростой, поэтому предлагается использовать следующий код:

static void GetX509Subject(CK_BYTE_PTR cert

//

Сертификат в двоичном представлении

 

 

, int certSize

 

// Размер

сертификата

 

 

, CK_BYTE_PTR* subject

// Указатель на

массив информации о субъекте

 

 

, int* subjectSize

// Размер

информации о субъекте

 

 

) {

 

 

unsigned int i;

 

 

unsigned char* current = cert;

 

 

unsigned char* prev;

 

 

unsigned char* end = cert + certSize;

 

unsigned char tags[] = {0x30, 0,

 

//

основная последовательность

 

 

0x30, 0,

 

//

последовательность, подписываемая ЭЦП

 

 

0xa0, 1,

 

// версия

23

0x02, 1,

// серийный

номер

 

0x30, 1,

// подпись

0x30, 1,

// издатель

0x30, 1,

// период

действия

 

0x30, 1,

// информация

о субъекте

 

};

 

*subject = NULL;

 

*subjectSize = 0;

 

for (i=0; i<sizeof(tags); i+=2)

 

{

 

unsigned char v; unsigned int length = 0; prev = current;

if (current+2>end) return;

if (*current++ != tags[i]) return; v = *current++;

if ((v & 0x80) == 0) length = v; else

{

unsigned char lenlen = v & 0x7f;

if (current + lenlen > end) return; for (v=0; v<lenlen; v++) length =

(length<<8) + *current++;

}

if (tags[i+1]) current+=length;

}

*subject = prev;

*subjectSize = (int)(current-prev);

}

Рассмотрим функцию CreateCertFromBlob(CK_SESSION_HANDLE hSession, CK_BYTE_PTR cert, int certSize, CK_BYTE_PTR subject, int subjSize). Данная функция предназначена для записи сертификата на eToken. Обратите внимание, что одним из параметров данной функции является переменная типа CK_SESSION_HANDLE hSession. Данная переменная является дескриптором сессии работы с токеном. Для того, чтобы получить данный дескриптор, используйте функцию C_OpenSession() из списка функций pFunctionList. В

качестве параметров к данной функции передаются идентификатор

24

слота, к котрому подключен eToken, флаги CKF_SERIAL_SESSION и CKF_RW_SESSION, 2 параметра NULL, так как не используется механизм обратного вызова и уведомления, и ссылка на дескриптор &hSession. Кроме того, необходимо произвести вход под ролью пользователя на токен, с использованием функцию C_Login() из списка функций pFunctionList. В качестве параметров к данной функции передаются дескриптор сессии hSession, роль пользователя CKU_USER, ПИН-код в формате BYTE (LPBYTE)password, длина ПИН-кода strlen(password).

Рассмотрим код данной функции CreateCertFromBlob: static bool CreateCertFromBlob(CK_SESSION_HANDLE hSession

// ID сессии

, CK_BYTE_PTR cert

// сертификат

, int certSize

//размер сертификата

,CK_BYTE_PTR subject

//субъект сертификата

,int subjSize

//размер субъекта

)

{

CK_OBJECT_CLASS classAttr = CKO_CERTIFICATE; CK_CERTIFICATE_TYPE certType = CKC_X_509; unsigned long certCategory = 2;

CK_BBOOL trueVal = CK_TRUE; CK_OBJECT_HANDLE hObject;

CK_ATTRIBUTE templateArray [] =

{

{CKA_CLASS, &classAttr, sizeof(classAttr)}, {CKA_CERTIFICATE_TYPE, &certType,

sizeof(certType)},

{CKA_TOKEN, &trueVal, sizeof(trueVal)}, {CKA_SUBJECT, subject, subjSize }, {CKA_VALUE, (void *)cert, certSize }, {CKA_CERTIFICATE_CATEGORY, (void

*)&certCategory, sizeof (certCategory) }, };

int sizeOfTemplate = sizeof (templateArray) / sizeof(CK_ATTRIBUTE);

25

CK_RV rv = pFunctionList->C_CreateObject ( hSession, templateArray, sizeOfTemplate, &hObject );

if (rv) {

return false;

}

return true;

}

Здесь создается объект класса CKO_CERTIFICATE, выбирается тип сертификата CKC_X_509, категория сертификата 2, дескриптор создаваемого объекта hObject, затем создается набор атрибутов, которые присущи объекту “Сертификат x.509” на eToken, в состав которого входят указанные ранее значения, а также сам сертификат и субъект сертификата в двоичном представлении. Создается сертификат

спомощью функции C_CreateObject, которая создает объект на токене

суказанным набором атрибутов templateArray.

Также здесь используется переменная rv – она отображается результат выполнения запроса к библиотеке eToken API. Если rv = 0, значит запрос был выполнен корректно, в противном случае значение этой переменной будет соответствовать коду ошибки. Все коды ошибок находятся в файле pkcs11t.h, начинаясь с CKR.

Для получения идентификатора слота, к которому подключен eToken используйте следующую функцию:

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)) {

26

slotID =

pSlotIDs[i];

break;

}

}

}

}

}

}

if (pSlotIDs) {

delete[] pSlotIDs; pSlotIDs = NULL_PTR;

}

return slotID;

}

Дополните функцию ImportCertificate процедурами закрытия сессии:

pFunctionList->C_Logout( hSession ); pFunctionList->C_CloseSession( hSession );

Проверьте работоспособность программы. Загрузите с помощью нее созданный сертификат на eToken. Проверьте наличие сертификата с помощью eToken PKI Client (Значок в панели задач –> Open eToken Properties -> Advanced View).

27

Рисунок 3 – Проверка наличия сертификата на eToken

4. Задание на лабораторную работу

Необходимо создать сертификат студента, подписанный с помощью сертификата преподавателя. Требуется написать программу, которая импортирует сертификат x.509 в DER кодировке на eToken. В данной программе необходимо: произвести инициализацию библиотеки PKCS#11 для eToken, запросить путь к сертификату на жестком диске, ПИН для подключения к eToken, произвести операцию Login к eToken, считать сертификат с жестокого диска, скопировать сертификат на eToken. Проверить наличие сертификата с помощью eToken PKI Client.

5.Контрольные вопросы

1.Что такое x.509?

2.Опишите структуру сертификата x.509.

3.Опишите формат использования утилиты makecert.exe?

4.Каким образом производится подключение пользователя к eToken?

5.Как создается сертификат x.509 на eToken?

28

6. Каким образом можно проверить наличие сертификата на eToken?

29

ЛАБОРАТОРНАЯ РАБОТА №3 Разработка подсистемы обеспечения целостности

1. Цель работы

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

2. Краткие теоретические сведения

Закрытый ключ RSA.

В алгоритме шифрования RSA, к отрытому ключу относят открытую экспоненту и модуль {e,n}, к закрытому ключу закрытую экспоненту и модуль {d,n} соответственно https://ru.wikipedia.org/wiki/RSA. eToken для ускорения вычислений,

использует другие компоненты – сами простые числа p и q, функцию эйлера и две дополнительные экспоненты, которые также относят к закрытому ключу. Можно рассмотреть примерную структуру PEM файла, в соответствии с которой компоненты закрытого ключа расположены. В соответствии с данной структурой, перед каждым из компонентов ключа, предварительно указывается длина компонента, затем идет сам компонент.

Рисунок 1 – Структура PEM файла

30