Создание объекта "открытый ключ" не на токене, а как объекта сессии.

Исходные данные: два Rutoken ЭЦП 2 и библиотека PKCS11. На первом токене создана ключевая пара (ГОСТ 2012), с помощью которой подписываются данные. С помощью второго токена нужно проверить эту подпись.

На основе значения открытого ключа из первого токена (получил из атрибута CKA_VALUE) пытаюсь создать объект "открытый ключ" на втором токене. В документации на сайте сказано, что нельзя создавать такой объект в "долговременной памяти". Поэтому я попытался создать его как объект сессии (для этого указал значение атрибута CKA_TOKEN равным FALSE). Создание заканчивается ошибкой CKR_ATTRIBUTE_VALUE_INVALID.

Для создания использовал вот такой шаблон

CK_OBJECT_CLASS     class_pub = CKO_PUBLIC_KEY;
СK_KEY_TYPE             key_type = CKK_GOSTR3410;
CK_ATTRIBUTE           tmpl_pub_2[] =
{
    { CKA_CLASS, &class_pub, sizeof(class_pub) },
    { CKA_KEY_TYPE, &key_type, sizeof(key_type) },
    { CKA_VALUE, NULL, 0 },
    { CKA_GOSTR3410_PARAMS, NULL, 0 },
    { CKA_GOSTR3411_PARAMS, NULL, 0 },
    { CKA_TOKEN, &p11_false, sizeof(p11_false) },
    { CKA_PRIVATE, &p11_false, sizeof(p11_false) },
};

OID-ы параметров брал из открытого ключа на первом токене.

Тему https://forum.rutoken.ru/topic/2621/ видел, но из нее так и не понял можно ли создавать объект открытый ключ как "сессионный" объект (т.е. не объект токена).

Если "сессионный" объект открытый ключ создать нельзя, можно ли как-то проверить подпись с помощью только вашей pkcs11 библиотеки?

Re: Создание объекта "открытый ключ" не на токене, а как объекта сессии.

Не увидел раздел "Техническая поддержка разработчиков". Просьба к модераторам: можно ли тему перенести туда?

(2020-07-10 08:12:47 отредактировано Павел Анфимов)

Re: Создание объекта "открытый ключ" не на токене, а как объекта сессии.

BE, добрый день!

Ошибка возникает из-за неверных атрибутов:

{ CKA_GOSTR3410_PARAMS, NULL, 0 },
{ CKA_GOSTR3411_PARAMS, NULL, 0 },

При создании ключа в памяти (CKA_TOKEN=FALSE) нужно указывать все атрибуты, что и при генерации через C_GenerateKeyPair.

CK_ATTRIBUTE publicKeyTemplate1[] =
{
    { CKA_CLASS, &publicKeyObject, sizeof(publicKeyObject)},                                        // Класс - открытый ключ
    { CKA_LABEL, &publicKeyLabelGost2012_256_1, sizeof(publicKeyLabelGost2012_256_1) - 1},          // Метка ключа
    { CKA_ID, &keyPairIdGost2012_256_1, sizeof(keyPairIdGost2012_256_1) - 1 },                      // Идентификатор ключевой пары #1 (должен совпадать у открытого и закрытого ключей)
    { CKA_KEY_TYPE, &keyTypeGostR3410_2012_256, sizeof(keyTypeGostR3410_2012_256) },                // Тип ключа - ГОСТ Р 34.10-2012(256)
    { CKA_TOKEN, &attributeFalse, sizeof(attributeFalse)},                                            // Ключ НЕ является объектом токена
    { CKA_PRIVATE, &attributeFalse, sizeof(attributeFalse)},                                        // Ключ доступен без аутентификации на токене
    { CKA_GOSTR3410_PARAMS, parametersGostR3410_2012_256, sizeof(parametersGostR3410_2012_256) },   // Параметры алгоритма ГОСТ Р 34.10-2012(256)
    { CKA_GOSTR3411_PARAMS, parametersGostR3411_2012_256, sizeof(parametersGostR3411_2012_256) }    // Параметры алгоритма ГОСТ Р 34.11-2012(256)
};

Все значения констант есть в примере из Рутокен SDK: <sdk>pkcs11/samples/Standard/CreateGOST34.10-2012-256

Re: Создание объекта "открытый ключ" не на токене, а как объекта сессии.

Добрый день.

Павел Анфимов пишет:

BE, добрый день!

Все значения констант есть в примере из Рутокен SDK: <sdk>pkcs11/samples/Standard/CreateGOST34.10-2012-256

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

Мне нужно на токен_2 создать объект "открытый ключ". Этот открытый ключ должен соответствовать открытому ключу из пары, созданной на токене_1. На токен_2 у меня нет закрытого ключа.

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

Re: Создание объекта "открытый ключ" не на токене, а как объекта сессии.

BE, атрибуты (набор CK_ATTRIBUTE) открытого ключа (кроме CKA_TOKEN) не должны отличаться, что при создании на токене_1, что на токене_2.

Re: Создание объекта "открытый ключ" не на токене, а как объекта сессии.

Внимательно посмотрел код создания объекта "открытый ключ" на токен_2 и нашел ошибку. Как Вы писали, она оказалась связанной с OID-ами (в шаблоне правились не те атрибуты). Теперь объект "открытый ключ" создается успешно, но возникает другая проблема.

Вызов C_VerifyInit(hses, &mech, hpub) заканчивается ошибкой CKR_KEY_TYPE_INCONSISTENT.

В чем может быть дело?

Переменная mech формируется следующим образом

CK_MECHANISM    mech = { 0 };

mech.mechanism = значение атрибута CKA_KEY_TYPE из ключа hpub.

При создании ключа используется следующий шаблон

CK_ATTRIBUTE            tmpl_pub_1[] =
{
    { CKA_GOSTR3410_PARAMS, NULL, 0 }, // этот атрибут заполняется на основе данных об открытом ключе
    { CKA_GOSTR3411_PARAMS, NULL, 0 }, // этот атрибут заполняется на основе данных об открытом ключе
    { CKA_CLASS, &class_pub, sizeof(class_pub) },
    { CKA_LABEL, NULL, 0 }, // этот атрибут заполняется на основе данных об открытом ключе
    { CKA_ID, NULL, 0 }, // этот атрибут заполняется на основе данных об открытом ключе
    { CKA_KEY_TYPE, &key_type, sizeof(key_type) },
    { CKA_TOKEN, &p11_false, sizeof(p11_false) },
    { CKA_PRIVATE, &p11_false, sizeof(p11_false) },
    { CKA_VERIFY, &p11_true, sizeof(p11_true) }, // добавил специально, думал, может поможет
    { CKA_VALUE, NULL, 0 }, // этот атрибут заполняется на основе данных об открытом ключе
};

Re: Создание объекта "открытый ключ" не на токене, а как объекта сессии.

Переменная mech формируется следующим образом
CK_MECHANISM    mech = { 0 };

mech.mechanism = значение атрибута CKA_KEY_TYPE из ключа hpub.

В mech.mechanism нужно класть CKM_GOSTR3410, если ключ ГОСТ-2001/ГОСТ-2012-256. Или CKM_GOSTR3410_512, если ГОСТ-2012-512.

Re: Создание объекта "открытый ключ" не на токене, а как объекта сессии.

Павел Анфимов пишет:

Переменная mech формируется следующим образом
CK_MECHANISM    mech = { 0 };

mech.mechanism = значение атрибута CKA_KEY_TYPE из ключа hpub.

В mech.mechanism нужно класть CKM_GOSTR3410, если ключ ГОСТ-2001/ГОСТ-2012-256. Или CKM_GOSTR3410_512, если ГОСТ-2012-512.

К сожалению, не помогло. Могу ли я подготовить минимальный пример и загрузить сюда как файл?

Re: Создание объекта "открытый ключ" не на токене, а как объекта сессии.

BE, да, конечно, присылайте.

Re: Создание объекта "открытый ключ" не на токене, а как объекта сессии.

Здравствуйте, Павел Анфимов.

1.
К сожалению минимальный пример оказался не таким уж минимальным (почти 800 строчек кода). Часть функций надерганы из вашего SDK.

Хуже всего, что в процессе написания примера я утратил знание о том, как создавать объект "открытый ключ" в сессии :( Перепробовал все, что возможно, но снова ключ так и не создается.

Буду признателен за Вашу помощь.

Заранее благодарен.

2.
Не могу приаттачить файл: "К сожалению загрузка файлов/изображений для вашей группы не доступна. Обратитесь к администрации форума."

Re: Создание объекта "открытый ключ" не на токене, а как объекта сессии.

напишите нам письмо с вложением hotline@rutoken.ru

Re: Создание объекта "открытый ключ" не на токене, а как объекта сессии.

Павел Анфимов пишет:

напишите нам письмо с вложением hotline@rutoken.ru

Отправил.

Re: Создание объекта "открытый ключ" не на токене, а как объекта сессии.

Здравствуйте, Павел Анфимов.

Вашу идею с двумя разными сессиями и одним токеном проверил, все работает. Спасибо.

Возник вот какой вопрос.

Вот здесь https://forum.rutoken.ru/post/11686/#p11686 написано о развороте открытого ключа, хеша и подписи. Открытый ключ и подпись при этом соответствуют представлению в CMS.

Правильно ли я понимаю, что хеш нужно обязательно разворачивать перед использованием в PKCS11 библиотеке?

Re: Создание объекта "открытый ключ" не на токене, а как объекта сессии.

BE, в PKCS данные нужно передавать в litte-endian.