Функции расшифрования

C_DecryptInit

Примечание

Функции C_Decrypt(), C_DecryptUpdate() и C_DecryptFinal() не возвращают предусмотренного стандартом PKCS #11 кода ошибки CKR_ENCRYPTED_DATA_INVALID (недопустимые зашифрованные данные).

CK_RV C_DecryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
Параметры:
  • hSession (in) – дескриптор сеанса.
  • pMechanism (in) – указатель на механизм. Идентификатор механизма задается в поле mechanism.
  • hKey (in) – дескриптор ключа расшифрования.

Инициализирует и задает параметры для операции расшифрования. Поддерживается как аппаратное, так и программное расшифрование.

Особенности апплетов:

  • Криптотокен 2 ЭП

    Аппаратное шифрование

    Для аппаратного шифрования используется виртуальный секретный ключ. Данный ключ должен быть предварительно импортирован с помощью функции C_UnwrapKey() или сгенерирован и экспортирован с помощью функции C_WrapKey().

    При использовании виртуального секретного ключа функция инициализирует операцию зашифрования по ГОСТ 28147–89 с параметрами id-tc26-gost-28147-param-Z.

    После импорта ключа атрибут CKA_KT2_KEY_ACTIVE принимает значение CK_TRUE, ключ готов к криптографическому преобразованию.
    После завершения операции преобразования ключ удаляется из памяти изделия, а атрибут CKA_KT2_KEY_ACTIVE принимает значение CK_FALSE.

    Программное шифрование

    Программное шифрование применяется стандартным способом.

    Для программного шифрования доступен атрибут CKA_KT2_KEY_MESHING. Если атрибут имеет значение CK_TRUE, применяется алгоритм усложнения ключей для ГОСТ 28147–89 RFC 4357 п.2.3.2.

Поддерживаются следующие механизмы:

  • Криптотокен
    • CKM_GOST28147_ECB (0x00001221) – механизм для симметричного шифра в режиме ECB по стандарту ГОСТ 28147–89.
    • CKM_GOST28147 (0x00001222) – механизм для симметричного шифра в режиме CFB по стандарту ГОСТ 28147–89.
  • Криптотокен 2 ЭП
    • CKM_GOST28147_ECB (0x00001221) – механизм для симметричного шифра в режиме ECB по стандарту ГОСТ 28147–89.
    • CKM_GOST28147 (0x00001222) – механизм для симметричного шифра в режиме CFB по стандарту ГОСТ 28147–89.
  • Laser
    • CKM_RSA_PKCS (0x00000001) – механизм для асимметричного шифра RSA. Также используется для ЭП.
    • CKM_RSA_PKCS_OAEP (0x00000009) – механизм для асимметричного шифра RSA с использованием OAEP.
    • CKM_DES3_ECB (0x00000132) – механизм для симметричного шифра triple-DES в режиме ECB.
    • CKM_DES3_CBC (0x00000133) – механизм для симметричного шифра triple-DES в режиме CBC.
    • CKM_AES_ECB (0x00001081) – механизм для симметричного шифра AES в режиме ECB.
    • CKM_AES_CBC (0x00001082) – механизм для симметричного шифра AES в режиме CBC.

Запускается в режимах

Результат:
  • CKR_CRYPTOKI_NOT_INITIALIZED – функция не может быть выполнена, т.к. библиотека еще не была инициализирована (см. C_Initialize()).
  • CKR_DEVICE_ERROR – возникла проблема с токеном и/или слотом.
  • CKR_DEVICE_MEMORY – памяти токена недостаточно для данной операции.
  • CKR_DEVICE_REMOVED – токен был изъят из слота.
  • CKR_FUNCTION_CANCELED – функция была отменена в момент исполнения.
  • CKR_FUNCTION_FAILED – выполнение функции было прервано или она не может быть выполнена.
  • CKR_GENERAL_ERROR – общий сбой при работе с библиотекой.
  • CKR_HOST_MEMORY – компьютер, на котором запущена библиотека, не имеет достаточно памяти для выполнения функции.
  • CKR_KEY_FUNCTION_NOT_PERMITTED – атрибуты ключа не позволяют его использование данным образом.
  • CKR_KEY_HANDLE_INVALID – недопустимый дескриптор ключа.
  • CKR_KEY_SIZE_RANGE – размер ключа лежит за пределами, поддерживаемыми библиотекой.
  • CKR_KEY_TYPE_INCONSISTENT – данный ключ невозможно использовать с указанным механизмом.
  • CKR_MECHANISM_INVALID – недопустимый механизм.
  • CKR_MECHANISM_PARAM_INVALID – недопустимый параметр механизма.
  • CKR_OK – функция выполнена успешно.
  • CKR_OPERATION_ACTIVE – на устройстве уже есть активная операция, что не позволяет начать новую операцию.
  • CKR_SESSION_CLOSED – сеанс был закрыт в момент выполнения функции.
  • CKR_SESSION_HANDLE_INVALID – недопустимый дескриптор сеанса.
  • CKR_USER_NOT_LOGGED_IN – действие не может быть выполнено, т.к. пользователь не залогинен.

Совет

Полный список ошибок см. в приложении.

C_Decrypt

CK_RV C_Decrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedData, CK_ULONG_PTR pulEncryptedDataLen, CK_BYTE_PTR pData, CK_ULONG ulDataLen, )
Параметры:
  • hSession (in) – дескриптор сеанса.
  • pEncryptedData (in) – указатель на зашифрованные данные.
  • pulEncryptedDataLen (in) – размер зашифрованных данных.
  • pData (out) – указатель на исходные данные.
  • ulDataLen (out) – размер данных.

Осуществляет единоразовое расшифрование (по ГОСТ 28147-89), т.е расшифровывает только один блок данных.

Предупреждение

При шифровании с использованием механизма CKM_GOST28147_ECB длина данных должна быть кратной 8 байт.

Запускается в режимах

Результат:
  • CKR_ARGUMENTS_BAD – недопустимые аргументы.
  • CKR_BUFFER_TOO_SMALL – вывод функции слишком велик для предоставленного буфера.
  • CKR_CRYPTOKI_NOT_INITIALIZED – функция не может быть выполнена, т.к. библиотека еще не была инициализирована (см. C_Initialize()).
  • CKR_DEVICE_ERROR – возникла проблема с токеном и/или слотом.
  • CKR_DEVICE_MEMORY – памяти токена недостаточно для данной операции.
  • CKR_DEVICE_REMOVED – токен был изъят из слота.
  • CKR_ENCRYPTED_DATA_LEN_RANGE – недопустимый размер зашифрованных данных.
  • CKR_FUNCTION_CANCELED – функция была отменена в момент исполнения.
  • CKR_FUNCTION_FAILED – выполнение функции было прервано или она не может быть выполнена.
  • CKR_GENERAL_ERROR – общий сбой при работе с библиотекой.
  • CKR_HOST_MEMORY – компьютер, на котором запущена библиотека, не имеет достаточно памяти для выполнения функции.
  • CKR_OK – функция выполнена успешно.
  • CKR_OPERATION_NOT_INITIALIZED – в указанном сеансе нет активной операции данного типа.
  • CKR_SESSION_CLOSED – сеанс был закрыт в момент выполнения функции.
  • CKR_SESSION_HANDLE_INVALID – недопустимый дескриптор сеанса.
  • CKR_USER_NOT_LOGGED_IN – действие не может быть выполнено, т.к. пользователь не залогинен.

Совет

Полный список ошибок см. в приложении.

C_DecryptUpdate

CK_RV C_DecryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart, CK_ULONG_PTR pulEncryptedPartLen)
Параметры:
  • hSession (in) – дескриптор сеанса.
  • pEncryptedPart (in) – указатель на зашифрованный блок данных.
  • pulEncryptedPartLen (in) – размер зашифрованного блока данных.
  • pPart (out) – указатель на блок исходных данных.
  • ulPartLen (out) – размер блока данных.

Продолжает составную операцию расшифрования – расшифровывает очередной блок данных.

Предупреждение

При шифровании с использованием механизма CKM_GOST28147_ECB длина данных должна быть кратной 8 байт.

Запускается в режимах

Результат:
  • CKR_ARGUMENTS_BAD – недопустимые аргументы.
  • CKR_BUFFER_TOO_SMALL – вывод функции слишком велик для предоставленного буфера.
  • CKR_CRYPTOKI_NOT_INITIALIZED – функция не может быть выполнена, т.к. библиотека еще не была инициализирована (см. C_Initialize()).
  • CKR_DEVICE_ERROR – возникла проблема с токеном и/или слотом.
  • CKR_DEVICE_MEMORY – памяти токена недостаточно для данной операции.
  • CKR_DEVICE_REMOVED – токен был изъят из слота.
  • CKR_ENCRYPTED_DATA_LEN_RANGE – недопустимый размер зашифрованных данных.
  • CKR_FUNCTION_CANCELED – функция была отменена в момент исполнения.
  • CKR_FUNCTION_FAILED – выполнение функции было прервано или она не может быть выполнена.
  • CKR_GENERAL_ERROR – общий сбой при работе с библиотекой.
  • CKR_HOST_MEMORY – компьютер, на котором запущена библиотека, не имеет достаточно памяти для выполнения функции.
  • CKR_OK – функция выполнена успешно.
  • CKR_OPERATION_NOT_INITIALIZED – в указанном сеансе нет активной операции данного типа.
  • CKR_SESSION_CLOSED – сеанс был закрыт в момент выполнения функции.
  • CKR_SESSION_HANDLE_INVALID – недопустимый дескриптор сеанса.
  • CKR_USER_NOT_LOGGED_IN – действие не может быть выполнено, т.к. пользователь не залогинен.

Совет

Полный список ошибок см. в приложении.

C_DecryptFinal

CK_RV C_DecryptFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pLastEncryptedPart, CK_ULONG_PTR pulLastEncryptedPartLen)
Параметры:
  • hSession (in) – дескриптор сеанса.
  • pLastEncryptedPart (out) – последний зашифрованный блок.
  • pulLastEncryptedPartLen (out) – размер последнего зашифрованного блока.

Завершает составную операцию расшифрования.

Запускается в режимах

Результат:
  • CKR_ARGUMENTS_BAD – недопустимые аргументы.
  • CKR_BUFFER_TOO_SMALL – вывод функции слишком велик для предоставленного буфера.
  • CKR_CRYPTOKI_NOT_INITIALIZED – функция не может быть выполнена, т.к. библиотека еще не была инициализирована (см. C_Initialize()).
  • CKR_DEVICE_ERROR – возникла проблема с токеном и/или слотом.
  • CKR_DEVICE_MEMORY – памяти токена недостаточно для данной операции.
  • CKR_DEVICE_REMOVED – токен был изъят из слота.
  • CKR_ENCRYPTED_DATA_LEN_RANGE – недопустимый размер зашифрованных данных.
  • CKR_FUNCTION_CANCELED – функция была отменена в момент исполнения.
  • CKR_FUNCTION_FAILED – выполнение функции было прервано или она не может быть выполнена.
  • CKR_GENERAL_ERROR – общий сбой при работе с библиотекой.
  • CKR_HOST_MEMORY – компьютер, на котором запущена библиотека, не имеет достаточно памяти для выполнения функции.
  • CKR_OK – функция выполнена успешно.
  • CKR_OPERATION_NOT_INITIALIZED – в указанном сеансе нет активной операции данного типа.
  • CKR_SESSION_CLOSED – сеанс был закрыт в момент выполнения функции.
  • CKR_SESSION_HANDLE_INVALID – недопустимый дескриптор сеанса.
  • CKR_USER_NOT_LOGGED_IN – действие не может быть выполнено, т.к. пользователь не залогинен.

Совет

Полный список ошибок см. в приложении.

Пример использования

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

Для единоразовой операции расшифрования Для составной операции расшифрования
  1. C_DecryptInit(),
  2. C_Decrypt().
  1. C_DecryptInit(),
  2. C_DecryptUpdate() (один или более раз),
  3. C_DecryptFinal().

Примеры Криптотокен

Пример реализации зашифрования на языке C:

// сеанс PKCS#11
CK_SESSION_HANDLE pkcs11SessionHandle;
// механизм расшифрования ГОСТ 28147-89
CK_MECHANISM pkcs11DecMechanism;
// дескриптор сессионного ключа PKCS#11
CK_OBJECT_HANDLE pkcs11SessionKeyHandle;
// текст, зашифрованный PKCS#11
CK_BYTE pkcs11EncText[8];
// длина текста, зашифрованного PKCS#11
CK_ULONG pkcs11EncTextLength = sizeof(pkcs11EncText);
// открытый текст
CK_BYTE plainText[8];
// длина открытого текста
CK_ULONG plainTextLength = sizeof(plainText);
// инициализационный вектор для шифрования
CK_BYTE encIV[8];
// длина открытого текста
CK_ULONG encIVLength = sizeof(encIV);

// устанавливаем механизм шифрования по ГОСТ 28147-89
pkcs11DecMechanism.mechanism = CKM_GOST28147;
pkcs11DecMechanism.pParameter = encIV;
pkcs11DecMechanism.ulParameterLen = encIVLength;

// инициализируем операцию расшифрования
rv = C_DecryptInit(pkcs11SessionHandle, &pkcs11DecMechanism, pkcs11SessionKeyHandle);
if(rv != CKR_OK)
{
  PrintError("C_DecryptInit", rv);
  return;
}

// расшифровываем зашифрованный текст
rv = C_Decrypt(pkcs11SessionHandle, pkcs11EncText, pkcs11EncTextLength, plainText, &plainTextLength);
if(rv != CKR_OK)
{
  PrintError("C_Decrypt", rv);
  return;
}

Примеры Криптотокен 2 ЭП

Пример аппаратного расшифрования с использованием виртуального секретного ключа на языке C++:

CK_BBOOL bTrue = CK_TRUE;
CK_BBOOL bFalse = CK_FALSE;

// зашифрованные данные
CK_BYTE encrypted[] = { ... };

// размер зашифрованных данных
CK_ULONG nEncrypted = 8;

// буфер расшифрованных данных
CK_BYTE decrypted[8] = { 0x00 };

// размер буфера расшифрованных данных
CK_ULONG nDecrypted = 8;

// получение дескриптора сессии (см. C_OpenSession)
CK_SESSION_HANDLE hSession = ... ;

// получение закрытого ключа Отправителя
CK_OBJECT_HANDLE hSenderPrivateKey = ... ;

// получение открытого ключа Получателя
CK_OBJECT_HANDLE hReceiverPublicKey = ... ;

/*
   В данном примере для генерации ключевых пар использовались следующие параметры:

   1. Механизм генерации ключей:

      CK_MECHANISM ckKeyGenMach = { CKM_GOSTR3410_256_KEY_PAIR_GEN, NULL_PTR, 0 };

   2. Шаблон закрытого ключа:

      CK_ATTRIBUTE privateKeyAttributes[] =
      {
        { CKA_TOKEN, &bTrue, sizeof(bTrue) },
        { CKA_PRIVATE, &bTrue, sizeof(bTrue) },
        { CKA_WRAP, &bTrue, sizeof(bTrue) },
        { CKA_UNWRAP, &bTrue, sizeof(bTrue) },
      };

   3. Шаблон открытого ключа:

      CK_ATTRIBUTE publicKeyAttributes[] =
      {
        { CKA_TOKEN, &bTrue, sizeof(bTrue) },
        { CKA_PRIVATE, &bFalse, sizeof(bFalse) },
        { CKA_GOSTR3410_PARAMS, id_GostR3410_2001_CryptoPro_XchA_ParamSet, sizeof(id_GostR3410_2001_CryptoPro_XchA_ParamSet) },
        { CKA_GOSTR3411_PARAMS, id_tc26_gost3411_12_256, sizeof(id_tc26_gost3411_12_256) },
        { CKA_WRAP, &bTrue, sizeof(bTrue) },
        { CKA_UNWRAP, &bTrue, sizeof(bTrue) },
      };
*/

CK_OBJECT_CLASS ckaClass = CKO_SECRET_KEY;
CK_BYTE ckaId[]          = "VSKO_ID"; // "VSKO_ID"

// атрибуты поиска виртуального ключа
CK_ATTRIBUTE searchAtt[] = {
  {CKA_CLASS, &ckaClass, sizeof(ckaClass)},
  {CKA_ID, ckaId, sizeof(ckaId) - 1}
};

CK_OBJECT_HANDLE hVirtualSecretKey = CK_INVALID_HANDLE; // дескриптор виртуального секретного ключа
CK_ULONG ulObjectsCount            = 5;

// поиск виртуального ключа
C_FindObjectsInit(hSession, searchAtt, 2);
C_FindObjects(hSession, &hVirtualSecretKey, 1, &ulObjectsCount);
C_FindObjectsFinal(hSession);

// параметры экспорта ключа
CK_GOSTR3410_KEY_WRAP_PARAMS wrapParams;
memset(&wrapParams, 0, sizeof(wrapParams));

wrapParams.hKey = hSenderPrivateKey;

CK_MECHANISM ckWrapMechanism;
ckWrapMechanism.mechanism      = CKM_GOSTR3410_KEY_WRAP;
ckWrapMechanism.pParameter     = &wrapParams;
ckWrapMechanism.ulParameterLen = sizeof(wrapParams);

// получаем требуемый размер для экспортного представления
CK_ULONG wrappedKeySize = 0;
C_WrapKey(hSession, &ckWrapMechanism, hReceiverPublicKey, hVirtualSecretKey, NULL, &wrappedKeySize);

// генерируем и экспортируем ключ hVirtualSecretKey
std::vector<CK_BYTE> wrappedKey(wrappedKeySize);
C_WrapKey(hSession, &ckWrapMechanism, hReceiverPublicKey, hVirtualSecretKey, &wrappedKey[0], &wrappedKeySize);

CK_BYTE plain[] = "12345678";
CK_BYTE encrypted[8] = {0x00};
CK_ULONG nEncrypted = 8;

CK_MECHANISM ckEncryptMech = { CKM_GOST28147 };
C_EncryptInit(hSession, &ckEncryptMech, hVirtualSecretKey);
C_Encrypt(hSession, &plain[0], 8, &encrypted[0], &nEncrypted);

// шаблон секретного ключа
CK_OBJECT_CLASS objectClass      = CKO_SECRET_KEY;
CK_KEY_TYPE keyType              = CKK_GOST28147;

CK_ATTRIBUTE secretKeyTemplate[] =
{
  {CKA_GOST28147_PARAMS, STR_CRYPTO_PRO_GOST28147_Z, STR_CRYPTO_PRO_GOST28147_Z_SIZE},
  {CKA_TOKEN, &s_TrueValue, sizeof(s_TrueValue)},
  {CKA_PRIVATE, &s_TrueValue, sizeof(s_TrueValue)},
  {CKA_CLASS, &objectClass, sizeof(objectClass)},
  {CKA_KEY_TYPE, &keyType, sizeof(keyType)},
  {CKA_DECRYPT, &s_TrueValue, sizeof(s_TrueValue)}
};

CK_OBJECT_HANDLE hCEK = CK_INVALID_HANDLE;

// импорт ключа в память изделия
wrapParams.hKey = hSenderPublicKey;
C_UnwrapKey(hSession, &ckWrapMechanism, hReceiverPrivateKey, &wrappedKey[0], wrappedKeySize, secretKeyTemplate, 6, &hCEK);

CK_BYTE decrypted[8] = { 0x00 };
CK_ULONG nDecrypted = 8;

CK_MECHANISM ckDecryptMech = { CKM_GOST28147 };
C_DecryptInit(hSession, &ckDecryptMech, hCEK);
C_Decrypt(hSession, &encrypted[0], 8, &decrypted[0], &nDecrypted);

Оглавление