Невозможно проинициализировать cryptoki библиотеку jcpkcs11 2 dll

Обновлено: 06.07.2024

Да, однажды сталкнулся с такой ситуацией, точнее - драйвер устанавливается, но сама jacara не определяется - через диспечер устройств ищем автоматом драйверы и не находит, хотя клиент джакарты стоит новый.

Если поискать на сайте производителя - можно найти более свежий драйвер - именно для Windows 10. Чуть ранее - он был не совместим с предыдущими операционными системами, сейчас - спокойно устанавливается на любую ОС от ХР до 10-ки.

На всякий случай, выкладываю ссылку на последнюю версию, данная версия подходит для всех современных ОС Windows и работает с ключами для ЕГАИС

Требования к программному обеспечению

На компьютере должна быть установлена одна из нижеперечисленных операционных систем:

  • Microsoft Windows 10 (32/64-бит);
  • Microsoft Windows 8.1 (32/64-бит);
  • Microsoft Windows 8 (32/64-бит);
  • Microsoft Windows 7 SP1 (32/64-бит);
  • Microsoft Windows Vista SP2 (32/64-бит);
  • Microsoft Windows XP SP3 (32-бит), SP2 (64-бит);
  • Microsoft Windows Server 2012 R2;
  • Microsoft Windows Server 2012;
  • Microsoft Windows Server 2008 R2 SP1;
  • Microsoft Windows Server 2008 SP2 (32/64-бит);
  • Microsoft Windows Server 2003 R2 SP2 (32/64-бит);
  • Microsoft Windows Server 2003 SP2 (32/64-бит).
  • Обновлена библиотека jcPKCS11-2.dll до версии 2.1.3.1900
  • Обновлён МП КриптоПро CSP до версии 3.6.407.568
  • Обновлён мастер технической поддержки до версии 1.0.1.28
  • Исправлена проблема с установкой опции auto-update через реестр
  • Исправлена проблема просмотра различных сертификатов с одинаковым серийным номером
  • Добавлена поддержка токенов JaCarta WebPass
  • Добавлена утилита управления JaCarta WebPass Tool для работы с токенами JaCarta WebPass версии 1.0.0.50
  • Обновлено лицензионное соглашение
  • Добавлена возможность синхронизации PIN-кода и пароля Active Directory
  • Добавлен дистрибутив библиотек из состава "Криптотокен ЭП"
  • Устранена несовместимость с алгоритмом разблокировки запрос-ответ, используемом в JC-Client
  • Обновлена библиотека jcPKCS11.dll
  • Добавлена выборочная установка драйверов
  • Повышена надёжность работы программы установки: добавлены проверки запуска критически важных драйверов
  • Повышена надёжность работы программы установки: исключены вызовы JScript и VBScript
  • Добавлена возможность включения протоколирования через графический интерфейс
  • Обновлена версия библиотеки для работы с файловой системой токенов (jcFS)
  • Решена проблема работы на процессорах AMD Athlon 64, не поддерживающих инструкции AVX2

Если возникли проблемы можно ознакомится со статьей - ошибка установки сборки единого клиента Джакарты

2) Не устанавливается единый клиент джакарты на Windows XP SP1 & SP2:

Так же могут быть проблемы и с Windows XP SP2, единый клиент устанавливается, но оборудование не устанавливается. Выход - обновить ОС до SP3.

3) Ошибка установки сборки

Иногда приходится играться с аппаратными ключами, в 99% случаях все встает идеально, но иногда на кривых системах бывают сюрпризы - например ошибка "ошибка установки сборки". Выключение антивируса не помогло, но если нажимаем "ок" - идет откат и удаление почти установившейся программы. И соответственно - аппаратный ключ не работает. Можно конечно нагуглить другой драйвер, но можно обойти и эту беду.

Как сделал я - устанавливал этот самый единый клиент - получаю ошибку, ни чего не нажимаю, вставляю ключ Джакарту, драйвер успешно устанавливается, через диспечер задач убиваем процесс установщика - msiexec.exe и после этого - у нас все работает.

Для справки - не устанавливалось на Windows 7 x64, с KIS 2013.

Во вложении - единый клиент джакарты для Windows 7 x32 и x64 + Windows 10 x64.

Для тех кто не в теме - что это за зверь такой и для чего он нужен, это драйвер аппаратного ключа Джакарта (JaCarta) - на данном этапе - необходимый для работы в системе ЕГАИС.

4) Джакарта не определяется

Бывает что джакарта смертна и как правило внезапно смертна - если же она не видится в Едином клиенте джакарты, то возможно что она просто сдохла. Проявляться может по разному - не видится в принципе, при попытке ввести пин-код пишет что заблокирован и не предлагает разблокировать, при инициализации выдает ошибки или же везде все хорошо, но ключи на себя записывать не дает - все равно под замену!

Добрый день. При попытке установить УТМ - в логе agent.log ошибка
2019-11-25 18:29:10,643 ERROR ru.centerinform.terminal.agent.Agent - Ошибка запуска приложения
java.lang.IllegalStateException: File [C:/Windows/SysWOW64/jcPKCS11-2.dll] not exists
at ru.centerinform.terminal.agent.Agent.a(Unknown Source)
at ru.centerinform.terminal.agent.Agent.main(Unknown Source)

Все драйверы/утилиты jacarta удалены.
Версия драйверов Рутокен: 4.8.0.1. Подскажите, пожалуйста, почему УТМ не понимает, что в системе рутокен, а не джакарта?

  • Ксения Шаврова
  • Администратор
  • Неактивен

Нужно переустановить УТМ с подключенным Рутокен ЭЦП 2.0, чтобы произошла настройка библиотек.

Здравствуйте, ystal.

Нужно переустановить УТМ с подключенным Рутокен ЭЦП 2.0, чтобы произошла настройка библиотек.

  • Ксения Шаврова
  • Администратор
  • Неактивен

Тогда можно воспользоваться Утилитой исправления файлов конфигурации. Она должна настроить УТМ на правильные библиотеки.

Тогда можно воспользоваться Утилитой исправления файлов конфигурации. Она должна настроить УТМ на правильные библиотеки.

После установки утилиты получилось запустить агент через agent.bat, но 3 службы так и не запускаются. При попытке запустить вручную - Ошибка 1053:Служба не ответила на запрос своевременно. В каталогах transport, updater, monitoring, в папках bin не хватает исполняемых файлов, есть только transport.bat и transport.sh. Подкинул исполняемые файлы с другого ПК, но это не решило проблему.

  • Ксения Шаврова
  • Администратор
  • Неактивен

Иногда, переустановка не помогает. и каких-то файлов все еще не хватает.
Тогда предлагаю полностью удалить УТМ со всеми файлами и заново поставить версию 3.0.8 из личного кабинета.

Иногда, переустановка не помогает. и каких-то файлов все еще не хватает.
Тогда предлагаю полностью удалить УТМ со всеми файлами и заново поставить версию 3.0.8 из личного кабинета.

При чистой установке свежескачанного дистрибутива из личного кабинета мы возвращаемся к изначальной проблеме. [C:/Windows/SysWOW64/jcPKCS11-2.dll] not exists - в логе агента, УТМ не понимает, что в системе рутокен, а не джакарта.

  • Ксения Шаврова
  • Администратор
  • Неактивен

Во время установки у вас точно подключен Рутокен ЭЦП 2.0? И больше никаких ключей нет в компьютере?
УТМ сам настраивается на библиотеки того аппаратного ключа, который подключен в системе

Во время установки у вас точно подключен Рутокен ЭЦП 2.0? И больше никаких ключей нет в компьютере?
УТМ сам настраивается на библиотеки того аппаратного ключа, который подключен в системе

Никаких ключей в компьютере больше нет. На другом ПК с этим же ключем всё работает без проблем.

  • Ксения Шаврова
  • Администратор
  • Неактивен
  • Ксения Шаврова
  • Администратор
  • Неактивен

Произведено удаленное подключение.
Требовалась перезагрузка компьютера. Установка УТМ некорректно отрабатывала.
Всё настроено для работы с Рутокен ЭЦП 2.0.


JaCarta PKI - сертифицированные USB-токены и смарт-карты с аппаратной реализацией зарубежных криптоалгоритмов, предназначенные для работы с инфраструктурой открытых ключей (PKI).

JaCarta-2 ГОСТ - USB-токены и смарт-карты, предназначенные для использования в качестве сертифицированного средства ЭП (усиленной квалифицированной подписи — УКЭП) и полноценного СКЗИ в системах электронного документооборота (ЭДО), дистанционного банковского обслуживания (ДБО) и др. для обеспечения юридической значимости и неотказуемости действий пользователей, а также для обеспечения целостности и конфиденциальности передаваемых данных.

JaCarta SF/ГОСТ – продукт предназначен для безопасного хранения и транспортировки информации ограниченного доступа (ДСП, гостайна) и состоит из:

аппаратного средства, выполненного в форм-факторе USB-токена;

ПО для ввода в эксплуатацию, управления и администрирования.

Для выполнения действий данной инструкции необходимо установить следующее программное обеспечение:

  • библиотека libccid, libjcPKCS11-2;
  • пакеты libpcsclite1 и pcscd;
  • opensc;

Для установки в терминале введите команду:

И установить скачанный пакет:

Для проверки работы JaCartaа:
Подключите устройство к компьютеру.

Способ №1


Способ №2


путь до библиотеки libjcPKCS11-2.so может различаться

Для того чтобы определить путь до библиотеки libjcPKCS11-2.so введите команду:

Способ №3

графическая утилита XCA:

Для инициализации токена необходимо воспользоваться утилитой pkcs11-tool.

Для задания ПИН кода пользователя используйте команду:

--slot 0x1ffff — указывает в какой виртуальный слот подключено устройство. Как правило, это слот 0, но могут быть и другие значения – 1,2 и т.д.

--init-token – команда инициализации токена.

--pin - пин код пользователя JaCarta. По умолчанию имеет значение 11111111

--so-pin 00000000 – ПИН код администратора JaCarta PKI. По умолчанию имеет значение 00000000

--label 'JaCarta PKI' - метка(название) устройства.

--module - указывает путь до библиотеки libjcPKCS11-2.so


Внимание! Инициализация устройства удалит все данные на JaCarta PKI без возможности восстановления.

Проверка

Чтобы проверить наличие сертификатов и ключевых пар на токене JaCarta введите команду:

В результате в окне терминала отобразится информация обо всех сертификатах и ключевых парах, хранящихся на токене JaCarta:

Если после строчки выводится информация о ключах и сертификатах, то из токена можно считать сертификат (см. ниже).

Извлечение сертификата из токена

вместо нужно подставить ID который вы увидите в выводе команды

Если после строчки

нет ничего, значит устройство пустое. Следует обратиться к администратору или создать ключи и сертификат самостоятельно.

Создание ключевой пары

Для генерации ключевой пары в терминале следует ввести команду:

pkcs11-tool --module /usr/lib/ libjcPKCS11-2.so --label "название_ключа" --keypairgen --key- type rsa:2048 -l -- id 45

Создание самоподписанного сертификата

Для создания самоподписанного сертификата в терминале следует ввести команду:

после чего не выходя из openssl ввести команду engine dynamic -pre SO_PATH:/usr/lib/x86_64-linux-gnu/engines-1.1/pkcs11.so -pre ID:pkcs11 -pre LIST_ADD:1 -pre LOAD -pre MODULE_PATH:/usr/lib/libeToken.so:

1) В Astra Linux SE 1.6 pkcs11 libengine-pkcs11-openssl версии 1.0.2 не совместим с библиотекой libjcPKCS11-2.so. Для корректного функционирования, следует скачать и установить п одписанный пакет libengine-pkcs11-openssl1.1 версии 0.4.4-4 для Astra Linux Special Edition РУСБ.10015-01 (очередное обновление 1.6): libengine-pkcs11-openssl1.1_0.4.4-4_amd64.deb

В поле Common Name должно быть указано имя пользователя ОС.

1) Путь до библиотеки pkcs11.so может отличаться

Для того чтобы определить путь до библиотеки pkcs11.so введите команду:
$ find /usr/*(lib|lib64) -name pkcs11.so

2) Т.к. вышеуказанные команды должны быть неразрывны, их следует обязательно вбивать в консоли openssl Иначе openssl не сможет обратиться к закрытому ключу

3) Номер слота указывается в десятичной системе счисления. Число 131071 в шестнадцатеричной системе = 0x1ffff


Загрузка сертификата на токен

Создав свой личный сертификат, его следует загрузить на JaCarta:

Using slot 0 with a present token (0x0)
Public Key Object; RSA 2048 bits
label: название_ключа
ID: 45
Usage: encrypt, verify, wrap
Certificate Object, type = X.509 cert
label: имя_сертификата_в_токене
ID: 45

Установка дополнительный пакетов

Пуск - Настройки - Менеджер пакетов

через Быстрый фильтр или через поиск находим и отмечаем к установке следующие пакеты:

  • libccid
  • pcscd
  • libpam-p11
  • libpam-pkcs11
  • libp11-2
  • libengine-pkcs11-openssl
  • opensc

Либо воспользовавшись терминалом FLY:

Конвертируем сертификат в текстовый формат

где название_вашего_сертификата.pem - Ваш сертификат из токена в текстовом формате

Теперь нам необходимо прочитать с токена сертификат с нужным ID и записать его в файл доверенных сертификатов:
Добавляем сертификат в список доверенных сертификатов

Для привязки токена к определенному пользователю необходимо указать его домашнюю директорию, например таким образом:

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

Настраиваем аутентификацию

Пуск - утилиты - Терминал Fly

записываем в файл следующую информацию:

Name: Pam_p11
Default: yes
Priority: 800
Auth-Type: Primary
Auth: sufficient pam_p11_opensc.so /usr/lib/ libjcPKCS11-2.so

сохранить файл нажав Alt + X, а затем Y, и после этого выполнить команду:

в появившемся окне поставить отметку в Pam_p11 и нажать OK .

Пуск - утилиты - Терминал Fly

Блокировка компьютера при извлечении токена

Для настройки pkcs11_eventmgr служит файл конфигурации - /etc/pam_pkcs11/pkcs11_eventmgr.conf

Пример файла конфигурации представлен ниже:

После этого добавьте приложение pkcs11_eventmgr в автозагрузку и перезагрузитесь.

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

Веб-сайт содержит большой объем справочной информации об устройствах JaCarta.


Чтобы вам было проще понять эту информацию, перед её прочтением желательно:

Исходя из определения из Википедии:

Про APDU

APDU — “язык ассемблера” для устройств.

Более подробно об APDU-формате написано в этой статье, мы же опишем его проще. APDU-формат описывает способ общения с различными устройствами с помощью байтовых последовательностей. На практике это происходит следующим образом:

Токену или смарт-карте посылается байтовая последовательность;

Операционная система устройства обрабатывает эту последовательность в команду и посылает в ответ код возврата и, при необходимости, дополнительную информацию.

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

Репозиторий с примерами

Чтобы улучшить понимание представленных ниже примеров рекомендуем:

Выполнить настройку системы согласно README.

Попробовать собрать примеры.

Отформатировать устройство семейства Рутокен ЭЦП 2.0 с помощью примера ex0_format_token.

Цикл работы с токеном

Внутри заголовочного файла utils.h находится описание функций init_pkcs11, free_pkcs11, get_slot_list. Их определение мы дадим ниже.

Всю работу с токеном можно разделить на три этапа:

Подготовительный этап

Мы реализовали его внутри функции init_pkcs11:

Здесь происходит следующее:

Потом мы вызываем полученную функцию C_GetFunctionList и получаем уже саму структуру указателей на функции.

С помощью функции C_Initialize инициализируется загруженная библиотека. Функция C_Initialize в качестве аргумента принимает параметры инициализации библиотеки. Подробнее о них можно почитать здесь, для нас же важен флаг CKF_OS_LOCKING_OK. Его необходимо использовать, если мы хотим использовать библиотеку в нескольких потоках. В нашем примере мы могли бы опустить этот флаг.

Основной этап

Основной этап можно разделить на работу со слотами и работу внутри сессии

Этап работы со слотами

Слот — это дескриптор виртуального интерфейса, куда подключен токен. Конкретно в нашем примере весь этап работы со слотами уместился в определение одной функции get_slot_list:

Работа со слотами происходит примерно в такой последовательности:

Получение списка слотов с помощью функции C_GetSlotList или через функцию ожидания событий, связанных со слотами (пример будет рассмотрен ниже).

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

Этап работы внутри сессии

Сессия — это дескриптор контекста выполнения последовательности операций. Обычно во время сессий выполняются основные функции работы с токеном или смарт-картой: шифрование, подпись и т.п. В нашем случае выполняется смена PIN-кода:

Работу внутри сессий можно разделить на несколько этапов:

Открытие сессии в слоте с помощью функции C_OpenSession.

Аутентификация пользователя с помощью функции C_Login. Стандартно на Рутокене присутствуют два пользователя: Администратор (CKU_SO) и Пользователь (CKU_USER). Аутентификация на устройстве — не является обязательной операцией. Она нужна, когда мы хотим получить доступ к операциям и объектам, которые требуют наличия соответствующих прав доступа. В нашем случае, это операция смены PIN-кода Пользователя.

Выполнение различных функций по работе с сессиями. В нашем случае это функция C_SetPIN.

Далее по нисходящей могут идти операции сброса прав доступа (C_Logout) и завершения сессии (C_CloseSession).

Завершающий этап

Весь наш завершающий этап поместился внутри определения функции free_pkcs11:

Завершающий этап можно разделить на:

Деинициализацию библиотеки с помощью функции C_Finalize.

Выгрузку библиотеки из памяти процесса через функцию FreeLibrary (для Linux-систем имеется обертка).

Стандартные функции и функции расширения

Стандартные — те, что явно описаны в стандарте. Список указателей на эти функции можно получить с помощью функции C_GetFunctionList, хранящейся в этой же библиотеке. Сами же стандартные функции имеют префикс "C_".

Расширения — те, что были добавлены разработчиками библиотеки и не описаны в стандарте. Стандарт явно не определяет функцию для получения списка расширенных функций. Но в библиотеке rtpkcs11ecp этой функцией является C_EX_GetFunctionListExtended. Сами же функции-расширения обычно имеют префикс "C_EX_".

Разделение по предназначению

Функции общего назначения. Например, для получения списка функций или получения информации о библиотеке.

Функции работы со слотами. Они не зависят от контекста работы с токеном. Например, C_GetSlotInfo, C_GetTokenInfo и т.п.

Функции для работы с сессиями. Как уже говорилось ранее, обычно во время выполнения этих функций осуществляется основное взаимодействие с токеном. При выполнении функции внутри сессии контекст работы с токеном не теряется. Самый простой пример этих функций: функция аутентификации (C_Login), функции работы с закрытым ключом на токене (C_Sign, C_Encrypt) и т.п.

Атомарные и составные операции

Работа со слотами

Получение списка слотов

Первый вызов функции C_GetSlotList позволяет получить количество доступных слотов. Это позволяет в дальнейшем выделять память под необходимое количество слотов. Второй вызов позволяет получить список слотов.

Первым аргументом C_GetSlotList является флаг, говорящий библиотеке, возвращать ли только слоты с подключенными устройствами (CK_TRUE) или нет (CK_FALSE).

Мониторинг событий слотов и получение информации о слоте

Тем не менее, хоть функция C_GetSlotList и является самой часто используемой, она неудобна при написании приложений, которые хотят динамически следить за состоянием слотов. Особенно это может быть критично при написании многопоточных приложений. На помощь может прийти функция мониторинга событий слотов C_WaitForSlotEvent. Она прерывает свою работу при любом изменении состояния какого-либо слота и возвращает идентификатор измененного слота. Работа с этой функцией выглядит примерно следующим образом:

Первым аргументом в функцию C_WaitForSlotEvent передается флаг блокировки (CKF_DONT_BLOCK). Если он установлен, то функция не является блокирующей. В таком случае, если никакой слот не был изменен, то возвращается код CKR_NO_EVENT.

Также стоит обратить внимание на использование функции получения информации о слоте C_GetSlotInfo. Мы использовали ее для определения наличия токена по флагу CKF_TOKEN_PRESENT. Подробнее с этой структурой можно ознакомиться здесь.

В этом файле представлен пример получения информации о подключенных токенах или смарт-картах с помощью функции C_GetTokenInfo. С помощью этой функции можно получить серийный номер, метку и другие характеристики подключенного устройства.

Объекты

Создание объектов — на примере генерации ключевых пар

В этом примере для нас много нового. Можно заметить, что здесь вызывается всего одна функция C_GenerateKeyPair. Эта функция является стандартной функцией генерации ключей, работающей внутри открытой сессии. Также стоит отметить, что пользователь должен быть аутентифицирован перед вызовом этой функции.

Cryptoki recognizes a number of classes of objects, as defined in the CK_OBJECT_CLASS data type. An object consists of a set of attributes, each of which has a given value. Each attribute that an object possesses has precisely one value.

То есть стандарт не даёт явное определение объекта, но из того, что там написано, мы знаем:

объект относится к определенному классу;

объект состоит из множества атрибутов, имеющих заданное значение;

каждый атрибут имеет ровно одно значение.

Также в стандарте представлена классификация объектов:

Заголовок диаграммы определяет класс объекта, а то что ниже — некоторые из его атрибутов.
Видно, что объектом может являться некоторый механизм (о механизмах мы поговорим позже), встроенные функции токена (Hardware feature), некоторые данные на токене (Storage). В нашем случае мы выполнили действие с данными.

Название всех атрибутов начинается с префикса "CKA_". Одним из самых важных атрибутов является CKA_ID. Он задаёт идентификатор объекта и используется для связи ключевых пар и сертификатов. Атрибут CKA_TOKEN является булевым и показывает, является ли объект — объектом токена. Атрибут CKA_PRIVATE тоже является булевым и определяет нужна ли предварительная аутентификация для получения доступа к объекту. Атрибут CKA_ID — задаёт шестнадцатеричный идентификатор объекта. Также есть булевые атрибуты CKA_MODIFIABLE, CKA_COPYABLE, CKA_DESTROYABLE для более тонкой настройки доступа к объекту. Подробнее про возможные атрибуты конкретных классов объектов можно прочитать непосредственно в самом стандарте для каждого класса объектов.

Объекты данных могут быть самыми разнообразными: асимметричные ключи, симметричные ключи, сертификаты, просто какая-либо информация на токене. В нашем примере мы создали два объекта, но сделали это неявно с помощью механизма генерации ключей. C_GenerateKeyPair приняла на вход механизм генерации ключевой пары, шаблоны открытого и закрытого ключа и с помощью механизма сгенерировала объекты ключевой пары (publicKey и privateKey). Мы пока ещё не описывали механизмы, но, говоря простым языком, механизм — это идентификатор операции, которая выполняет какую-то криптографическую функцию. В нашем случае — это функция генерации объекта.

Поиск объектов и создание сырой подписи

В прошлом разделе мы сгенерировали ключевую пару. На этот раз будем считать, что у нас нет хендлов на сгенерированные ключи, но мы знаем их идентификатор – CKA_ID. Попробуем найти объект закрытого ключа на токене:

Данный пример иллюстрирует работу с функцией поиска объекта по заданным атрибутам. Как можно заметить, операция поиска объекта на токене является составной и работа с ней сводится как минимум к вызову трёх функций: C_FindObjectsInit, C_FindObjects, C_FindObjectsFinal. Функция C_FindObjects может вызываться по несколько раз, и каждый раз она будет возвращать следующие объекты поиска. Предпоследний аргумент функции C_FindObjects задаёт размер выходного массива объектов. А последний — количество полученных объектов после очередного поиска.

Поиск приватного ключа производился по атрибуту его класса и идентификатору. Мы рассчитывали, что найдётся хотя бы один объект по заданному шаблону и брали любой из них. Используем найденный ключ для вычисления сырой подписи:

В этом примере подпись и хеш можно считать одновременно. Такой вариант рекомендован для безопасности: цепочку "хеширование-подпись" лучше не «разрывать». Чтобы показать, какой алгоритм хеширования использовать, мы передали его OID.

Также имеется возможность считать сырую подпись в два этапа: сначала брать хеш от данных, а затем вычислялась подпись от хеша. Такой подход более модульный, т.к. алгоритмы хеширования и вычисления подписи могут быть любыми и их можно комбинировать. Естественно, комбинировать можно с некоторыми ограничениями, которые налагаются стандартами, например, на длину хеша.

Работа с функциями расширения на примере создания запроса на сертификат

Можно заметить, что работа с функциями расширения очень похожа на работу со стандартными функциями. Основное отличие лишь в том, что мы обращаемся к другому списку функций CK_FUNCTION_LIST_EXTENDED_PTR. Создание запроса на сертификат происходит в одну строчку функцией C_EX_CreateCSR и возвращает запрос в DER-формате. Также стоит обратить внимание, что память, выделенную внутри библиотеки, следует высвобождать с помощью функции C_EX_FreeBuffer.

По полученному запросу можно получить сертификат в Удостоверяющем центре. Например, воспользуемся тестовым УЦ КриптоПро для получения сертификата. Полученный сертификат необходимо скачать в DER-формате, сохранить в файле с именем "cert_2012-256.cer" и положить в директорию, из которой вы запускаете примеры. Полученный сертификат можно импортировать на токен.

Импорт сертификата на токен. Создание объекта вручную

Сертификаты на токене так же как и ключи — являются объектами. Сертификат можно импортировать на токен, создав объект с нужными атрибутами. Для этого мы реализовали функцию: import_cert:

На этот раз мы создали объект напрямую с помощью функции C_CreateObject. Для создания объекта сертификата мы аналогично передали шаблон с атрибутами объекта: тело сертификата, идентификатор, тип доступа, тип сертификата и т.п.

Функцию C_CreateObject можно использовать не только для создания сертификата на токене, но и для создания других объектов, например, публичных ключей (CKO_PUBLIC_KEY), закрытых ключей (CKO_PRIVATE_KEY), симметричных ключей (CKO_SECRET_KEY), обычных данных (CKO_DATA). Их значение будет также содержаться внутри атрибута CKA_VALUE.

Теперь, когда у нас на токене имеется и ключевая пара и сертификат, для закрепления материала рассмотрим операцию создания CMS-подписи.

Формирование CMS-подписи

Данная возможность является расширением библиотеки Рутокен и может работать только с ГОСТ-ключами. Для создания подписи в формате CMS требуется наличие закрытого ключа и сертификата (неявно содержащего в себе открытый ключ). Создание CMS-подписи реализовано в функции sign_cms:

Получение и установка атрибутов публичных объектов

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

Логика работы с функцией C_SetAttributeValue очень похожа на логику создания объектов — создаётся шаблон, атрибуты заполняются указанными значениями. Все это передаётся на вход функции C_SetAttributeValue. Изменять атрибуты можно, если у объекта атрибут CKA_MODIFIABLE равен CK_TRUE.

При получении значений атрибутов иногда неизвестно, какой будет выходной размер атрибута. В таком случае создается шаблон с нулевыми значениями указателей на выходные объекта атрибутов и их размеров. Этот шаблон передаётся функции C_GetAttributeValue. Функция заполняет значение выходных размеров атрибутов в этом шаблоне. Мы может воспользоваться этой информацией для выделения памяти под атрибуты в шаблоне и дальнейшего вызова функции C_GetAttributeValue.

Для демонстрации работы функций C_GetAttributeValue и C_SetAttributeValue рассмотрим пример получения тела сертификата и изменения текстовой метки сертификата:

Про механизмы

Отсюда следует, что механизмы:

Определяют некоторое криптографическое преобразование.

Согласно документации механизмы можно разделить на:

Механизмы шифрования и расшифрования (Encrypt & Decrypt);

Механизмы подписи и проверки подписи (Sign & Verify);

Механизм формирования хеша (Digest);

Механизм генерации симметричных и асимметричных ключей (Gen. Key/Key Pair);

Экспорт и импорт ключей (Wrap & Unwrap);

Выработка общего ключа на основе асимметричных ключей (Derive).

Каждый механизм идентифицирует одну или несколько из этих функций. Так, например, ранее рассмотренный механизм CKM_GOSTR3410_KEY_PAIR_GEN предназначен для генерации ключей, а механизм CKM_AES_ECB может использоваться как для зашифрования/расшифрования, так и для свертки/развертки ключей.

Идентификатор механизма (mechanism);

Указатель на параметры механизма (pParameter);

Длина в байтах параметров механизма (ulParameterLen).

В этом примере стоит обратить внимание на то, как передаётся вектор инициализации механизму шифрования. Стоит заметить, что после вызова функции C_Encrypt вызывать функцию C_EncryptFinal не нужно: для многих механизмов вызов C_Encrypt эквивалентен последовательному вызову функций C_EncryptUpdate и C_EncryptFinal.

Проверка поддержки механизмов

Ранее в примерах мы всегда надеялись на то, что токен поддерживает используемые механизмы, но, вообще говоря, — это может быть не так. Так, например, Рутокен Lite не поддерживает криптографические механизмы. Поэтому перед началом работы с каким-либо механизмом желательно убедиться в том, что он поддерживается устройством. Это можно сделать с помощью функции C_GetMechanismList, которая возвращает список поддерживаемых механизмов токена. Напишем удобную обертку для проверки поддержки определенного механизма:

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

Утилита pkcs11-tool

Генерация ключевых пар:
pkcs11-tool --module /usr/lib/librtpkcs11ecp.so --keypairgen --key-type GOSTR3410-2012-256:B --id 45 -l

Создание сырой подписи:
pkcs11-tool --module /usr/lib/librtpkcs11ecp.so --sign --id 45 -l -i file.txt --mechanism GOSTR3410-WITH-GOSTR3411-12-256

Генерация псевдослучайных последовательностей:
pkcs11-tool --module /usr/lib/librtpkcs11ecp.so --generate-random 16

Получение списка объектов на токене:
pkcs11-tool --module /usr/lib/librtpkcs11ecp.so -O

Получение механизмов, поддерживаемых токеном:
pkcs11-tool --module /usr/lib/librtpkcs11ecp.so -M

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

Дополнительный материал

Выводы

OpenSSL API (pkcs11 engine, rutoken engine);

C++ с использованием библиотеки pki-core;

Если вы хотите узнать про какую-то реализацию подробнее, то напишите в комментариях и мы постараемся в ближайшее время выпустить новую статью с её разбором.

Читайте также: