BOOL WINAPI CPImportKey( HCRYPTPROV hProv, CONST BYTE * pbData, DWORD dwDataLen, HCRYPTKEY hImpKey, DWORD dwFlags, HCRYPTKEY * phKey );
Коды возврата | Описание |
---|---|
ERROR_INVALID_PARAMETER | Один из параметров содержит некорректное значение. Чаще всего это некорректный указатель. |
NTE_BAD_DATA | Не прошёл контроль целостности импортируемого ключевого блоба. Ошибочная длина блоба. |
NTE_BAD_FLAGS | Параметр dwFlags содержит ошибочную величину. |
NTE_BAD_KEY | Один или оба из ключей, указанных hKey и hImpKey, не действительны. Байты в элементах заголовка ключевого блоба типа WORD, DWORD имеют обратный порядок по отношению к данной платформе. |
NTE_BAD_TYPE | Тип ключевого блоба не поддерживается этим криптопровайдером и, возможно, ошибочен. |
NTE_PERM | Попытка импорта ключа, когда право импорта криптопровайдером не предоставлено. |
NTE_NO_MEMORY | Криптопровайдер во время операции исчерпал память. |
NTE_FAIL | Нарушение целостности ключей в ОЗУ. см. Дополнительные параметры и определения . |
SCARD_W_CANCELLED_BY_USER | Пользователь прервал операцию нажатием клавиши Cancel |
SCARD_W_WRONG_CHV | Пользователь ввёл неправильный пароль или пароль, установленный функцией SetProvParam(), неправильный |
SCARD_E_INVALID_CHV | Пользователь ввёл пароль с нарушением формата или пароль, установленный функцией SetProvParam(), имеет неправильный формат. Например, пароль имеет недопустимую длину или содержит недопустимые символы. |
SCARD_W_CHV_BLOCKED | Ввод Pin-кода был заблокирован смарт-картой, т.к. исчерпалось количество попыток, разрешенное картой для ввода. |
NTE_TOKEN_KEYSET_STORAGE_FULL | Недостаточно места на носителе для сохранения информации. |
NTE_SILENT_CONTEXT | Операция не может быть выполнена без пользовательского интерфейса. |
SCARD_W_REMOVED_CARD | Носитель контейнера был удалён из считывателя |
NTE_EXISTS | Попытка импортировать ключ в случае, когда ключ соответствующего типа в контейнере существует. |
NTE_NOT_SUPPORTED | Данный носитель не поддерживает импорт ключа. |
SCARD_E_NO_KEY_CONTAINER | Контекст открыт с флагом CRYPT_DEFAULT_CONTAINER_OPTIONAL, и не связан ни с одним контейнером, поэтому выполнение данной операции недоступно. |
Обычно для согласования (экспорта/импорта) сессионного ключа применяют алгоритм Диффи-Хеллмана. В этом случае ключ парной связи (ключ экспорта/импорта сессионного ключа) порождается операцией импорта открытого ключа получателя (отправителя) на ключевой паре отправителя (получателя). Т.е. для импорта сессионного ключа следует выполнить следующие шаги:
... CPGetUserKey(hProv, AT_KEYEXCHANGE, &hUserKey); ... CPImportKey(hProv, pbSenderPublicKey, cbSenderPublicKey, hUserKey, 0, &hExchKey); ALG_ID ke_alg = CALG_PRO_EXPORT; CPSetKeyParam(hProv, hExchKey, KP_ALGID, (LPBYTE)&ke_alg, 0); CPImportKey(hProv, pbSessionKeyFromSender, &cbSessionKeyFromSender, hExchKey, 0, &hSessionKey); ...
Для ключей 2012 в качестве алгоритма согласования сессионного ключа используется алгоритм VKO GOST R 34.10-2012-256 (на основе функции хэширования ГОСТ Р 34.11-2012-256), параметр KP_CIPHEROID результирующего ключа принимает значение, установленное в параметрах импортируемого открытого ключа (если не указано, то "1.2.643.7.1.2.5.1.1", вариант ТК26 Z). Режимы шифрования, преобразования ключа и дополнения открытого текста до кратности блока для получаемого ключа устанавливаются аналогично вновь создаваемому ключу (см. CPSetKeyParam()).
Для ключей 2001 используется алгоритм VKO GOST R 34.10-2001 (на основе функции хэширования ГОСТ Р 34.11-94). При использовании данного алгоритма с долговременным ключом параметр KP_CIPHEROID полученного ключа принимает oid параметров шифрования, установленный в соответствующем долговременному ключу контейнере; при использовании с эфемерным ключом параметр KP_CIPHEROID результирующего ключа принимает установленное для провайдера значение PP_CIPHEROID. Режимы шифрования, преобразования ключа и дополнения открытого текста до кратности блока для получаемого ключа устанавливаются аналогично вновь создаваемому ключу (см. CPSetKeyParam()).
В случае импорта SIMPLEBLOB набор узлов замены устанавливается в соответствии с указанным в блобе. Режимы шифрования, преобразования ключа и дополнения открытого текста до кратности блока для получаемого ключа устанавливаются аналогично вновь создаваемому ключу (см. CPSetKeyParam()).
В случае импорта OPAQUEKEYBLOB набор узлов замены, режимы шифрования, преобразования ключа и дополнения открытого текста до кратности блока устанавливаются в соответствии с параметрами, указанными в блобе.
С помощью этой же функции в режиме диверсификации ключа (CRYPT_DIVERSBLOB ) можно создавать ключи блоков (пакетов) на основе сессионного ключа.
// Пример получения ключа блока (пакета) на основе ключа сесcии (файла, ассоциации) // с помощью возможности диверсификации ключа функцией CPImportKey в соответствии с // алгоритмом, описанным в п.7 RFC 4357. // bBlockNumber - байтовая последовательность, диверсифицирующая ключ. Blob.DiversBlobHeader.BlobHeader.bType = DIVERSKEYBLOB; Blob.DiversBlobHeader.BlobHeader.bVersion = 0x20; Blob.DiversBlobHeader.BlobHeader.reserverd = 0; Blob.DiversBlobHeader.BlobHeader.aiKeyAlg = CALG_G28147; Blob.DiversBlobHeader.aiDiversAlgId = CALG_PRO_DIVERS; Blob.DiversBlobHeader.dwDiversMagic = 0x31564944; Blob.DiversBlobHeader.cbDiversData = sizeof(bBlockNumber); CopyMemory((LPBYTE)Blob.bDiversData,bBlockNumber,sizeof(bBlockNumber)); CPImportKey(hCSP, hProv, &Blob, sizeof(Blob), hSessionKey, 0, &hBlkKey); // Диверсификация в соответствии с алгоритмом KDF_GOSTR3411_2012_256 // проводится аналогично с тем отличием, что в поле aiDiversAlgId // записывается константа CALG_PRO12_DIVERS ...
С помощью этой же функции в режиме диверсификации ключа (CRYPT_KDF_TREE_DIVERSBLOB ) можно создавать ключи блоков (пакетов) на основе процедуры диверсификации КриптоПро CSP, предусматривающей возможность выработки нескольких ключей.
... // Пример выработки нескольких ключей на основе ключа диверсификации // с помощью алгоритма CALG_KDF_TREE_GOSTR3411_2012_256, описанного // в п.4.5 рекомендаций по стандартизации "Криптографические алгоритмы, // сопутствующие применению алгоритмов электронной цифровой подписи и функции хэширования" // bSeedData - байтовая последовательность Seed, диверсифицирующая ключ. // bLabelData - байтовая последовательность Label, диверсифицирующая ключ. dwBlobLen = sizeof(CRYPT_KDF_TREE_DIVERSBLOB_HEADER) + sizeof(CRYPT_KDF_TREE_DIVERS_INFO) + sizeof(bSeedData) + sizeof(bLabelData); DiversBlob.KdfTreeBlobHeader.BlobHeader.aiKeyAlg = CALG_G28147; DiversBlob.KdfTreeBlobHeader.BlobHeader.bType = KDF_TREE_DIVERSBLOB; DiversBlob.KdfTreeBlobHeader.BlobHeader.bVersion = BLOB_VERSION; DiversBlob.KdfTreeBlobHeader.BlobHeader.reserved = 0; DiversBlob.KdfTreeBlobHeader.aiDiversAlgId = CALG_KDF_TREE_GOSTR3411_2012_256; DiversBlob.KdfTreeBlobHeader.dwIterNum = 1; DiversBlob.KdfTreeDiversInfo.dwLabelLen = sizeof(bLabelData); DiversBlob.KdfTreeDiversInfo.dwSeedLen = sizeof(bSeedData); DiversBlob.KdfTreeDiversInfo.L_value = 1024; DiversBlob.KdfTreeDiversInfo.R_value = 2; CopyMemory((LPBYTE)DiversBlob.bDiversData, bSeedData, sizeof(bSeedData)); CopyMemory((LPBYTE)DiversBlob.bDiversData + sizeof(bSeedData), bLabelData, sizeof(bLabelData)); // Первичный вызов с передачей всех параметров диверсификации CPImportKey(hCSP, hProv, &DiversBlob, dwBlobLen, hSessionKey, 0, &hDivKey[0]); // Для последующих вызовов достаточно передачи хэдера с нужным номером ключа // Вызовы с различными номерами результирующих ключей могут идти не по порядку DiversBlob.KdfTreeBlobHeader.dwIterNum = 3; CPImportKey(hCSP, hProv, &DiversBlob.KdfTreeBlobHeader, sizeof(CRYPT_KDF_TREE_DIVERSBLOB_HEADER), hSessionKey, 0, &hDivKey[1]); ...
В качестве алгоритма согласования сессионного ключа может быть использован алгоритм Диффи-Хеллмана. Для этого при импорте открытого ключа получателя (отправителя) на ключевой паре отправителя (получателя) требуется указать флаг CP_FORCE_GOST_DH.
В случае импорта SIMPLEBLOB, PUBLICKEYBLOB или DIVERSKEYBLOB (при использовании алгоритмов диверсификации CALG_PRO_DIVERS и CALG_PRO12_DIVERS) разрешается многопоточная работа функции. Для этого в соответствующем вызове импорта необходимо передавать флаг CP_CRYPT_NOKEYWLOCK, при этом ключ hImpKey блокируется только на чтение. Корректность работы функции и целостность ключа импорта гарантируются криптопровайдером.
В случае импорта SIMPLEBLOB набор узлов замены устанавливается в соответствии с указанным в блобе. Режимы шифрования, преобразования ключа и дополнения открытого текста до кратности блока для получаемого ключа устанавливаются аналогично вновь создаваемому ключу (см. CPCSetKeyParam()).
В случае импорта OPAQUEKEYBLOB набор узлов замены, режимы шифрования, преобразования ключа и дополнения открытого текста до кратности блока устанавливаются в соответствии с параметрами, указанными в блобе.
Полученный дескриптор ключа должен в обязательном порядке быть удалён с помощью вызова функции CPDestroyKey() до вызова функции CPReleaseContext() для рабочего дескриптора криптопровайдера.
Пример согласования общего ключа с использованием флага CP_PRIMITIVE_PUBLICKEYBLOB:
... CryptExportKey(hEphemKey, 0, PUBLICKEYBLOB, CP_PRIMITIVE_PUBLICKEYBLOB, pbBlob, &dwBlobLen); CryptImportKey(hProv, pbBlob, dwBlobLen, hSecretKey, CP_PRIMITIVE_PUBLICKEYBLOB, &hCommonKey); ...
AIX: 6/7.
FreeBSD: 11/12, pfSense 2.x.
Linux: LSB 4.x (RHEL 5/6/7/8, SuSE 11SP4/12/15, Oracle Linux 5/6/7/8, CentOS 6/7/8, Ubuntu 14.04/16.04/18.04/19.10, Linux Mint 18/19, Fedora 28/29/30/31, Debian 8/9/10 и др.).
Solaris: 10/11.
Mac OS X: 10.9/10.10/10.11/10.12/10.13/10.14/10.15.
iOS: 8/9/10/11/12/13.
Sailfish: 2/3.
Windows: 7/8/8.1/10, Server 2008/2008R2/2012/2012R2/2016/2019.
Файл описания: Прототип описан в файле wincsp.h.
Ядро ОС: Вместо неё используется аналогичная функция CPCImportKey .
CRYPT_PRIVATEKEYBLOB ,CRYPT_PUBLICKEYBLOB ,CRYPT_SIMPLEBLOB ,CRYPT_DIVERSBLOB ,CPExportKey() ,CPGenKey() ,CPImportKey в MS CSP ,CryptImportKey в MS CryptoAPI 2.0