(2019-10-17 17:14:25 отредактировано Binger)

Проблемы с работой примера хэширования из SDK/pkcs11/sample/standart

Здравствуйте. Не понимаю в чём проблема: запустил пример из SDK по созданию хэша с входными данными "Hello crypto world" с использованием алгоритма ГОСТ 2012-256. Должен получить следующее:
dd b5 1e 17 37 cc 3d 5f b0 64 e3 c2 a cc b5 1a 47 9c c7 72 30 55 ca 3a 21 8c 2d e4 46 7c a7 12. На деле имеем:
http://forum.rutoken.ru/uploads/images/2019/10/49b00020ac189e5801d0d02e139e709b.png
Решил проверить те же входные данные с алгоритмом SHA-1, т.к. результат работы можно легко получить на различных сайтах онлайн. На выходе получаю следующие данные:
http://forum.rutoken.ru/uploads/images/2019/10/0ecc42f76c636a683b8ae7b5f0d416a1.png
Проверил на нескольких сайтах онлайн с этими же входными данными и получил совсем другой результат:
http://forum.rutoken.ru/uploads/images/2019/10/0467e144bd398167c03aaf254daf7477.png
http://forum.rutoken.ru/uploads/images/2019/10/179f2a7872d2af9df3cb71905e25df6a.png
Как такое возможно? Использую Рутокен ЭЦП 2.0.
Код прикреплю на всякий случай:

/*************************************************************************
* Rutoken                                                                *
* Copyright (c) 2003-2019, CJSC Aktiv-Soft. All rights reserved.         *
* Подробная информация:  http://www.rutoken.ru                           *
*------------------------------------------------------------------------*
* Пример работы с Рутокен при помощи библиотеки PKCS#11 на языке C       *
*------------------------------------------------------------------------*
* Использование команд вычисления хэш-кода:                              *
*  - установление соединения с Рутокен в первом доступном слоте;         *
*  - определение типа подключенного токена;                              *
*  - вычисление хэш-кода ГОСТ Р 34.11-2012(512);                         *
*  - закрытие соединения с Рутокен.                                      *
*------------------------------------------------------------------------*
* Данный пример является самодостаточным.                                *
*************************************************************************/

#include <Common.h>

/*************************************************************************
* Данные, от которых будет производиться вычисление хэш-кода             *
*************************************************************************/
static CK_BYTE data[] = { "Hello crypto world" };



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_BYTE_PTR hash;                                 // Указатель на временный буфер для хэш-кода данных
    CK_ULONG hashSize;                                // Размер временного буфера в байтах

    CK_RV rv;                                         // Код возврата. Могут быть возвращены только ошибки, определенные в PKCS#11

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

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

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

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

    /*************************************************************************
    * Загрузить библиотеку                                                   *
    *************************************************************************/
    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_GOSTR3411_12_256) {
            isGostR3411_12_256Supported = 1;
            break;
        }
    }

    CHECK_AND_LOG(" Checking CKM_GOSTR3411_12_256 support", isGostR3411_12_256Supported,
                  "CKM_GOSTR3411_12_512 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);

    printf("Initialization has been completed successfully.\n");

    /*************************************************************************
    * Вычислить хэш-код данных                                               *
    *************************************************************************/
    printf("\nHashing data...\n");

    /*************************************************************************
    * Инициализировать хэш-функцию                                           *
    *************************************************************************/
    rv = functionList->C_DigestInit(session, &gostR3411_2012_256HashMech);
    CHECK_AND_LOG(" C_DigestInit", rv == CKR_OK, rvToStr(rv), close_session);

    /*************************************************************************
    * Определить размер хэш-кода                                             *
    *************************************************************************/
    rv = functionList->C_Digest(session, data, sizeof(data), NULL_PTR, &hashSize);
    CHECK_AND_LOG(" C_Digest(get size)", rv == CKR_OK, rvToStr(rv), close_session);

    /*************************************************************************
    * Вычислить хэш-код данных                                               *
    *************************************************************************/

    hash = (CK_BYTE_PTR)malloc(hashSize * sizeof(CK_BYTE));
    CHECK("  Memory allocation for hash", hash != NULL, close_session);

    rv = functionList->C_Digest(session, data, sizeof(data), hash, &hashSize);
    CHECK_AND_LOG(" C_Digest (get hash)", rv == CKR_OK, rvToStr(rv), free_hash);

    /*************************************************************************
    * Распечатать буфер, содержащий хэш-код                                  *
    *************************************************************************/
    printf(" Hashed buffer is: \n");
    printHex(hash, hashSize);
    printf("Hashing has been completed.\n");

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

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

    /*************************************************************************
    * Очистить память, выделенную под хэш-код                                *
    *************************************************************************/
free_hash:
    free(hash);

    /*************************************************************************
    * Закрыть открытую сессию в слоте                                        *
    *************************************************************************/
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/sample/standart

Дело в том, что строки в Си заканчиваются на '\0' и именно это лишний символ искажает результат.
Нужно или записывать в виде массива байтов:

static CK_BYTE data[] = { 'H','e','l','l','o',' ','c','r','y','p','t','o',' ','w','o','r','l','d' };

Или в качестве размера данных передавать результат подсчета длины строки, чтобы '\0' не фигурировал.

    static char* data = "Hello crypto world";
    /*************************************************************************
    * Инициализировать хэш-функцию                                           *
    *************************************************************************/
    rv = functionList->C_DigestInit(session, &gostR3411_2012_256HashMech);
    CHECK_AND_LOG(" C_DigestInit", rv == CKR_OK, rvToStr(rv), close_session);

    /*************************************************************************
    * Определить размер хэш-кода                                             *
    *************************************************************************/
    rv = functionList->C_Digest(session, data, strlen(data), NULL_PTR, &hashSize);
    CHECK_AND_LOG(" C_Digest(get size)", rv == CKR_OK, rvToStr(rv), close_session);

    /*************************************************************************
    * Вычислить хэш-код данных                                               *
    *************************************************************************/

    hash = (CK_BYTE_PTR)malloc(hashSize * sizeof(char));
    CHECK("  Memory allocation for hash", hash != NULL, close_session);

    rv = functionList->C_Digest(session, data, strlen(data), hash, &hashSize);
    CHECK_AND_LOG(" C_Digest (get hash)", rv == CKR_OK, rvToStr(rv), free_hash);

Re: Проблемы с работой примера хэширования из SDK/pkcs11/sample/standart

Павел Анфимов, Павел, спасибо. Снова выручаете :-) Вы прекрасный специалист)) Хорошего вам дня, Павел.