DWORD CPCAPI CPCImportKey( HCRYPTMODULE hCSP, 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 | Попытка импортировать ключ в случае, когда ключ соответствующего типа в контейнере существует. |
ERROR_FUNCTION_FAILED | нет лицензии, дающей право на выполение функции импорта ключа |
Обычно для согласования (экспорта/импорта) сессионного ключа применяют алгоритм Диффи-Хеллмана. В этом случае ключ парной связи (ключ экспорта/импорта сессионного ключа) порождается операцией импорта открытого ключа получателя (отправителя) на ключевой паре отправителя (получателя). Т.е. для импорта сессионного ключа следует выполнить следующие шаги:
Однако, в ядре ОС отсутствует поддержка долговременных ключей. Поэтому ключ сессии (на файл или ассоциацию) или ключевая пара для ЭЦП обычно передаются из поддерживающего сервиса (демона). Для этого сначала вырабатывается совместный ключ (hDrvKey):
... // Инициализация работы с драйвером CPCGetProvParam(hCSP, hProv, PP_RANDOM, pbRandomBlobToDriver, cbRandomBlobToDriver); ... // Передать инициализатор ДСЧ (pbRandomBlobToDriver) в поддерживающий сервис и // получить от него случайную последовательность (pbRandomFromDriver). ... CPCCreateHash(hCSP, hProv, CALG_GR3411, 0, 0, &hDrvHash); CPCHashData(hCSP, hProv, hDrvHash, "DriverDaemon", sizeof("DriverDaemon"), 0); CPCHashData(hCSP, hProv, hDrvHash, pbRandomBlobToDriver, cbRandomBlobToDriver, 0); CPCHashData(hCSP, hProv, hDrvHash, pbRandomFromDriver, cbRandomFromDriver, 0); CPCDeriveKey(hCSP, hProv, hDrvHash, &hDrvKey); CPCDestroyHash(hCSP, hProv, hDrvHash); ...
На этом ключе сервис может экспортировать ключевую пару для подписи:
... // Получение дескриптора ключевой пары: CPCGetUserKey(hCSP, hProv, AT_SIGNATURE, &hUserKey); // Подготовка ключевой пары для передачи в драйвер: CPCExportKey(hCSP, hProv, hUserKey, hDrvKey, PRIVATEKEYBLOB, 0, pbPrivateKeyForDriver, &cbPrivateKeyForDriver); ... // Передать pbPrivateKeyForDriver в драйвер ...
Аналогичным образом можно экспортировать ключ сессии:
... // Импорт ключа сессии (файла, ассоциации) от отправителя: CPCImportKey(hCSP, hProv, pbSenderPublicKey, cbSenderPublicKey, hUserKey, 0, &hExchKey); ALG_ID ke_alg = CALG_PRO_EXPORT; CPCSetKeyParam(hCSP, hProv, hExchKey, KP_ALGID, (LPBYTE)&ke_alg, 0); CPCImportKey(hCSP, hProv, pbSessionKeyFromSender, &cbSessionKeyFromSender, hExchKey, 0, &hSessionKey); // Подготовка его для передачи в драйвер CPCExportKey(hCSP, hProv, hSessionKey, hDrvKey, SIMPLEBLOB, 0, pbSessionKeyForDriver, &cbSessionKeyForDriver); ... // Передать pbSessionKeyForDriver в драйвер ...
На основе ключа сессии можно получить ключи блоков (пакетов) с помощью CPCGenKey(), CPCDeriveKey() или алгоритма диверсификации ключа в функции CPCImportKey() (CRYPT_DIVERSBLOB ).
... // Инициализация работы с демоном (сервисом) ... // Получить инициализатор ДСЧ (pbRandomBlobFromDaemon) в драйвер. ... CPCSetProvParam(hCSP, hProv, PP_RANDOM, pbRandomBlobFromDaemon); CPCGenRandom(hCSP, hProv, cbRandomToDaemon, pbRandomToDaemon); CPCCreateHash(hCSP, hProv, CALG_GR3411, 0, 0, &hDmnHash); CPCHashData(hCSP, hProv, hDmnHash, "DriverDaemon", sizeof("DriverDaemon"), 0); CPCHashData(hCSP, hProv, hDmnHash, pbRandomBlobFromDaemon, cbRandomBlobFromDaemon, 0); CPCHashData(hCSP, hProv, hDmnHash, pbRandomToDaemon, cbRandomToDaemon, 0); CPCDeriveKey(hCSP, hProv, hDmnHash, &hDmnKey); CPCDestroyHash(hCSP, hProv, hDmnHash); ... // Передать случайную последовательность демону (сервису). ... // Получить pbSessionKeyFromDaemon из демона (сервиса) ... CPCImportKey(hCSP, hProv, pbSessionKeyFromDaemon, &cbSessionKeyFromDaemon, hDmnKey, 0, &hSessionKey); ... // Вариант получения ключа блока (пакета) на основе ключа сесcии (файла, ассоциации) // с помощью CPCGenKey. CPCImportKey(hCSP, hProv, pbBlkBlob, cbBlkBlob, hSessionKey, 0, &hBlkKey); ... // Вариант получения ключа блока (пакета) на основе ключа сесcии (файла, ассоциации) // с помощью CPCDeriveKey. // bBlockNumber - указатель на байтовую последовательность, диверсифицирующая ключ. CPCCreateHash(hCSP, hProv, CALG_GR3411, 0, 0, &hHash); CPCHashData(hCSP, hProv, hHash, "DeriveBlkKey", sizeof("DeriveBlkKey"), 0); CPCHashSessionKey(hCSP, hProv, hHash, hSessionKey, 0); CPCHashData(hCSP, hProv, hHash, bBlockNumber, sizeof(dwBlockNumber), 0); CPCDeriveKey(hCSP, hProv, CALG_G28147, hHash, 0, &hBlkKey); CPCDestroyHash(hCSP, hProv, hHash); ... // Вариант получения ключа блока (пакета) на основе ключа сесcии (файла, ассоциации) // с помощью возможности диверсификации ключа функцией CPCImportKey. // 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)); CPCImportKey(hCSP, hProv, &Blob, sizeof(Blob), hSessionKey, 0, &hBlkKey); ...
Ядро FreeBSD: 7/8/9 или выше
Ядро Linux: ядро 2.4.x/2.6.x/3.0.х/3.2.х или выше
Ядро Solaris: 10/11 или выше.
Ядро Windows 2000/XP/2003/Vista/2008/7: Необходимо Windows 2000 SP4 или старше.
CRYPT_PRIVATEKEYBLOB ,CRYPT_PUBLICKEYBLOB ,CRYPT_SIMPLEBLOB ,CRYPT_OPAQUEBLOB ,CRYPT_DIVERSBLOB ,CPCExportKey() ,CPCGenKey() ,CPImportKey в MS CSP ,CryptImportKey в MS CryptoAPI 2.0