(2019-09-27 17:35:42 отредактировано Binger)

Не ищет ключевую пару. SDK/pkcs11/samples/std/SignGOST34.10-2012-256

Здравствуйте. Вставил в компьютер токен рутокен ЭЦП 2.0, запускаю изложенный пример, а там выводит следующее:
https://forum.rutoken.ru/uploads/images/2019/09/fdfd7ab05eb449f665d00c445fb4df0f.png
В коде ничего не менял. В чём может быть причина? На пк скачал драйвера для windows с вашего сайта, установил панель управления рутокен. Получил сертификат от тестового УЦ CryptoPro с парой ключей на токен.
https://forum.rutoken.ru/uploads/images/2019/09/f9bcf678ef4cb237677877cac01d0750.png
Запарывается программа на этом месте:

/*************************************************************************
    * Получить массив хэндлов закрытых ключей                                *
    *************************************************************************/
    printf(" Getting signing key...\n");
r = findObjects(functionList, session, privateKeyTemplate, arraysize(privateKeyTemplate),
        &objects, &objectCount);
    CHECK(" findObjects", r == 0, logout);

Если рассмотреть шаблон privateKeyTemplate

CK_ATTRIBUTE privateKeyTemplate[] =
{
    { CKA_ID, &keyPairIdGost2012_256_1, sizeof(keyPairIdGost2012_256_1) - 1 },   // ID пары
    { CKA_CLASS, &privateKeyObject, sizeof(privateKeyObject) }                   // Класс - закрытый ключ
};

то можно увидеть использование ID пары, может её надо мне подправить? Стандартное определение:

/* DEMO ID пары ключей #1 ГОСТ Р 34.10-2012(256) */
static CK_BYTE keyPairIdGost2012_256_1[] = { "GOST R 34.10-2012 (256 bits) sample key pair 1 ID (Aktiv Co.)" };

Пробовал заменить на имя ключа, которое отображается в панели управления Рутокен, но ничего не изменилось:

static CK_BYTE keyPairIdGost2012_256_1[] = { "te-3dadf386-fdf2-4a01-b888-8726b8f9adb8" }

https://forum.rutoken.ru/uploads/images/2019/09/270705d0bfd3217c8f20dc77095245be.png

Что нужно мне сделать, чтобы пример заработал? Спасибо за Ваше внимание.

Если вдруг нужен код примера всего то вставлю, мало ли:

/*************************************************************************
* Rutoken                                                                *
* Copyright (c) 2003-2019, CJSC Aktiv-Soft. All rights reserved.         *
* Подробная информация:  http://www.rutoken.ru                           *
*------------------------------------------------------------------------*
* Пример работы с Рутокен при помощи библиотеки PKCS#11 на языке C       *
*------------------------------------------------------------------------*
* Использование команд вычисления/проверки ЭП на ключах                  *
* ГОСТ Р 34.10-2012 для длины ключа 256 бит:                             *
*  - установление соединения с Рутокен в первом доступном слоте;         *
*  - выполнение аутентификации Пользователя;                             *
*  - внутреннее хэширование и подпись сообщения                          *
*    на демонстрационном ключе;                                          *
*  - сброс прав доступа Пользователя на Рутокен и закрытие соединения    *
*    с Рутокен.                                                          *
*------------------------------------------------------------------------*
* Пример использует объекты, созданные в памяти Рутокен примером         *
* CreateGOST34.10-2012-256.                                              *
*************************************************************************/
#include "stdafx.h"
#include <Common.h>

/*************************************************************************
* Данные для цифровой подписи                                            *
*************************************************************************/
CK_BYTE data[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 };

/*************************************************************************
* Шаблон для поиска закрытого ключа для цифровой подписи                 *
*************************************************************************/

CK_ATTRIBUTE privateKeyTemplate[] =
{
    { CKA_ID, &keyPairIdGost2012_256_1, sizeof(keyPairIdGost2012_256_1) - 1 },   // ID пары
    { CKA_CLASS, &privateKeyObject, sizeof(privateKeyObject) }                   // Класс - закрытый ключ
};

int main(void)
{
    HMODULE module;                                  // Хэндл загруженной библиотеки PKCS#11
    CK_SESSION_HANDLE session;                       // Хэндл открытой сессии

    CK_FUNCTION_LIST_PTR functionList;               // Указатель на список функций PKCS#11, хранящийся в структуре CK_FUNCTION_LIST
    CK_C_GetFunctionList getFunctionList;            // Указатель на функцию C_GetFunctionList

    CK_SLOT_ID_PTR slots;                            // Массив идентификаторов слотов
    CK_ULONG slotCount;                              // Количество идентификаторов слотов в массиве

    CK_MECHANISM_TYPE_PTR mechanisms;                // Массив поддерживаемых механизмов
    CK_ULONG mechanismCount;                         // Количество поддерживаемых механизмов

    CK_OBJECT_HANDLE_PTR objects;                    // Массив хэндлов объектов, соответствующих критериям поиска
    CK_ULONG objectCount;                            // Количество хэндлов объектов в массиве

    CK_BYTE_PTR signature;                           // Указатель на буфер, содержащий цифровую подпись для данных
    CK_ULONG signatureSize;                          // Размер буфера, содержащего цифровую подпись для данных, в байтах

    CK_RV rv;                                        // Код возврата. Могут быть возвращены только ошибки, определенные в PKCS#11
    int r;                                           // Код возврата для функций, возвращающих int

    CK_ULONG i;                                      // Вспомогательная переменная-счетчик в циклах

    int isGostR3410w3411_256Supported = 0;           // Флаги для проверки поддержки токеном CKM_GOSTR3410_WITH_GOSTR3411_12_256

    int errorCode = 1;                               // Флаг ошибки

                                                     /*************************************************************************
                                                     * Выполнить действия для начала работы с библиотекой PKCS#11             *
                                                     *************************************************************************/
    printf("Initialization...\n");

    /*************************************************************************C
    * Загрузить библиотеку                                                   *
    *************************************************************************/
    module = LoadLibrary(PKCS11ECP_LIBRARY_NAME);
    CHECK(" LoadLibrary", module != NULL, exit);

    /*************************************************************************
    * Получить адрес функции запроса структуры с указателями на функции      *
    *************************************************************************/
    getFunctionList = (CK_C_GetFunctionList)GetProcAddress(module, "C_GetFunctionList");
    CHECK(" GetProcAddress", getFunctionList != NULL, unload_pkcs11);

    /*************************************************************************
    * Получить структуру с указателями на функции                            *
    *************************************************************************/
    rv = getFunctionList(&functionList);
    CHECK_AND_LOG(" Get function list", rv == CKR_OK, rvToStr(rv), unload_pkcs11);

    /*************************************************************************
    * Инициализировать библиотеку                                            *
    *************************************************************************/
    rv = functionList->C_Initialize(NULL_PTR);
    CHECK_AND_LOG(" C_Initialize", rv == CKR_OK, rvToStr(rv), unload_pkcs11);

    /*************************************************************************
    * Получить количество слотов c подключенными токенами                    *
    *************************************************************************/
    rv = functionList->C_GetSlotList(CK_TRUE, NULL_PTR, &slotCount);
    CHECK_AND_LOG(" C_GetSlotList (number of slots)", rv == CKR_OK, rvToStr(rv), finalize_pkcs11);

    CHECK_AND_LOG(" Checking available tokens", slotCount > 0, " No tokens available", finalize_pkcs11);

    /*************************************************************************
    * Получить список слотов c подключенными токенами                        *
    *************************************************************************/
    slots = (CK_SLOT_ID_PTR)malloc(slotCount * sizeof(CK_SLOT_ID));
    CHECK(" Memory allocation for slots", slots != NULL, finalize_pkcs11);

    rv = functionList->C_GetSlotList(CK_TRUE, slots, &slotCount);
    CHECK_AND_LOG(" C_GetSlotList", rv == CKR_OK, rvToStr(rv), free_slots);
    printf(" Slots available: %d\n", (int)slotCount);

    /*************************************************************************
    * Получить список поддерживаемых токеном механизмов                      *
    *************************************************************************/
    rv = functionList->C_GetMechanismList(slots[0], NULL_PTR, &mechanismCount);
    CHECK_AND_LOG(" C_GetMechanismList (number of mechanisms)", rv == CKR_OK, rvToStr(rv), free_slots);

    CHECK_AND_LOG(" Checking mechanisms available", mechanismCount > 0, " No mechanisms available", free_slots);

    mechanisms = (CK_MECHANISM_TYPE_PTR)malloc(mechanismCount * sizeof(CK_MECHANISM_TYPE));
    CHECK(" Memory allocation for mechanisms", mechanisms != NULL_PTR, free_slots);

    rv = functionList->C_GetMechanismList(slots[0], mechanisms, &mechanismCount);
    CHECK_AND_LOG(" C_GetMechanismList", rv == CKR_OK, rvToStr(rv), free_mechanisms);

    /*************************************************************************
    * Определение поддерживаемых токеном механизмов                          *
    *************************************************************************/
    for (i = 0; i < mechanismCount; ++i) {
        if (mechanisms[i] == CKM_GOSTR3410_WITH_GOSTR3411_12_256) {
            isGostR3410w3411_256Supported = 1;
            break;
        }
    }

    CHECK_AND_LOG(" Checking CKM_GOSTR3410_WITH_GOSTR3411_12_256 support", isGostR3410w3411_256Supported,
        "CKM_GOSTR3410_WITH_GOSTR3411_12_256 isn`t supported!\n", free_mechanisms);

    /*************************************************************************
    * Открыть RW сессию в первом доступном слоте                             *
    *************************************************************************/
    rv = functionList->C_OpenSession(slots[0], CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, &session);
    CHECK_AND_LOG(" C_OpenSession", rv == CKR_OK, rvToStr(rv), free_mechanisms);


    /*************************************************************************
    * Выполнить аутентификацию Пользователя                                  *
    *************************************************************************/
    rv = functionList->C_Login(session, CKU_USER, USER_PIN, USER_PIN_LEN);
    CHECK_AND_LOG(" C_Login", rv == CKR_OK, rvToStr(rv), close_session);
    printf("Initialization has been completed successfully.\n");

    /*************************************************************************
    * Сформировать цифровую подпись данных по алгоритму                      *
    * ГОСТ Р 34.10-2012(256)                                                 *
    *************************************************************************/
    printf("\nSigning data...\n");

    /*************************************************************************
    * Получить массив хэндлов закрытых ключей                                *
    *************************************************************************/
    printf(" Getting signing key...\n");

    r = findObjects(functionList, session, privateKeyTemplate, arraysize(privateKeyTemplate),
        &objects, &objectCount);
    CHECK(" findObjects", r == 0, logout);

    CHECK_AND_LOG(" Checking number of keys found", objectCount > 0, "No objects found\n", logout);

    /*************************************************************************
    * Сформировать цифровую подпись данных по алгоритму                      *
    * ГОСТ Р 34.10-2012(256)                                                 *
    *************************************************************************/
    printf(" Signing data...\n");

    /*************************************************************************
    * Инициализировать операцию подписи данных                               *
    *************************************************************************/
    rv = functionList->C_SignInit(session, &gostR3410_2012_256SigVerMech_WithInternalHash, objects[0]);
    CHECK_AND_LOG("  C_SignInit", rv == CKR_OK, rvToStr(rv), free_objects);

    /*************************************************************************
    * Определить размер данных подписи                                       *
    *************************************************************************/
    rv = functionList->C_Sign(session, data, sizeof(data), NULL_PTR, &signatureSize);
    CHECK_AND_LOG("  C_Sign (get size)", rv == CKR_OK, rvToStr(rv), free_objects);

    /*************************************************************************
    * Подписать данные                                                      *
    ************************************************************************/
    signature = (CK_BYTE*)malloc(signatureSize * sizeof(CK_BYTE));
    CHECK("  Memory allocation for signature", signature != NULL, free_objects);

    rv = functionList->C_Sign(session, data, sizeof(data), signature, &signatureSize);
    CHECK_AND_LOG("  C_Sign (signing)", rv == CKR_OK, rvToStr(rv), free_signature);

    /*************************************************************************
    * Распечатать буфер, содержащий подпись                                  *
    *************************************************************************/
    printf("  Signature buffer is: \n");
    printHex(signature, signatureSize);
    printf("Data has been signed successfully.\n");

    /*************************************************************************
    * Выставить признак успешного завершения программы                       *
    *************************************************************************/
    errorCode = 0;

    /*************************************************************************
    * Выполнить действия для завершения работы с библиотекой PKCS#11         *
    *************************************************************************/
    printf("\nFinalizing... \n");

    /*************************************************************************
    * Очистить память, выделенную под хэш-коды, подпись и объекты            *
    *************************************************************************/

free_signature:
    free(signature);

free_objects:
    free(objects);

    /*************************************************************************
    * Сбросить права доступа                                                 *
    *************************************************************************/
logout:
    rv = functionList->C_Logout(session);
    CHECK_RELEASE_AND_LOG(" C_Logout", rv == CKR_OK, rvToStr(rv), errorCode);

    /*************************************************************************
    * Закрыть открытую сессию в слоте                                        *
    *************************************************************************/
close_session:
    rv = functionList->C_CloseSession(session);
    CHECK_RELEASE_AND_LOG(" C_CloseSession", rv == CKR_OK, rvToStr(rv), errorCode);

    /*************************************************************************
    * Очистить память, выделенную под механизмы и слоты                      *
    *************************************************************************/
free_mechanisms:
    free(mechanisms);

free_slots:
    free(slots);

    /*************************************************************************
    * Деинициализировать библиотеку                                          *
    *************************************************************************/
finalize_pkcs11:
    rv = functionList->C_Finalize(NULL_PTR);
    CHECK_RELEASE_AND_LOG(" C_Finalize", rv == CKR_OK, rvToStr(rv), errorCode);

    /*************************************************************************
    * Выгрузить библиотеку из памяти                                         *
    *************************************************************************/
unload_pkcs11:
    CHECK_RELEASE(" FreeLibrary", FreeLibrary(module), errorCode);

exit:
    if (errorCode) {
        printf("\n\nSome error occurred. Sample failed.\n");
    }
    else {
        printf("\n\nSample has been completed successfully.\n");
    }

    return errorCode;
}

Re: Не ищет ключевую пару. SDK/pkcs11/samples/std/SignGOST34.10-2012-256

Здравствуйте! Пример отрабатывает корректно.
Причина в том, что вы пытаетесь работать с контейнером КриптоПро CSP через PKCS#11. Так работать не будет.
Если нужно работать именно с таким контейнером, вам нужен SDK КриптоПро CSP.
Чтобы работать через PKCS#11, нужно сгенерировать ключи и сертификат через PKCS#11. Например на ra.rutoken.ru

Re: Не ищет ключевую пару. SDK/pkcs11/samples/std/SignGOST34.10-2012-256

Огромное спасибо за помощь. Всё получилось после добавления контейнера Рутокен