| ||||
| ||||
Каким образом потом можно извлечь этот контейнер с токена, какие функции использовать? При условии, что есть возможность считать любой файл. Что было проделано - проверка на PFX не срабатывает. Просто как чтение сертификата из файла - тоже. Хочется, чтобы можно было подписывать с помощью сертификата в контейнере, чтобы можно было просматривать его свойства. | ||||
Ответы: | ||||
| ||||
Смотря какая схема использования ключа и сертификата: 1) Сертификат установлен в хранилище сертификатов Windows с привязкой к контейнеру секретного ключа. В этом случае можно использовать готовые приложения (например, Приложение командной строки, КриптоАРМ, MS Outlook,...) или вызовы из Вашего приложения высокоуровневых функций работы с сертификатами для ЭЦП и шифрования (CAPICOM или Simplified Message Functions или Low-level Message Functions). Они сами, когда будет нужно, вызовут функции CSP для доступа к ключу в контейнере. 2) Вы используете более низкоуровневые функции CryptoAPI для работы с контейнером, т.е. самостоятельно вызываете ф-ю открытия контекста (CryptAcquireContext), затем ф-ю чтения ключа (CryptGetUserKey), затем ф-ю чтения сертификата из контейнера(CryptGetKeyParam) и т.д. | ||||
| ||||
Сертификат не установлен в локальных хранилищах, поэтому использую способ два. Но возникли проблемы. Вызываю CryptAcquireContext так: CryptAcquireContext( &hProv, NULL, "Crypto-Pro GOST R 34.10-2001 Cryptographic Service Provider", 75, NULL), намереваясь получить дескриптор провайдера, чтобы дальше воспользоваться CryptGetProvParam с параметром PP_ENUMCONTAINERS, после чего имея имена контейнеров, вызывать опять CryptAcquireContext с именем контейнера, потом CryptGetUserKey и CryptGetKeyParam - как Вы и сказали (я же правильно мысль уловил?). После первого вызова CryptAcquireContext всплывает UI криптопровайдера, где показан список носителей, причем при выборе токена, говорит, что набор ключей не существует (оно и понятно, т.к. я NULL в имени контейнера передаю). Но чтобы мне получить имена контейнеров, мне надо заставить работать CryptAcquireContext. Замкнутый круг. Как его можно разорвать? | ||||
| ||||
Ну разумеется. Если не хотите, чтобы спрашивали носитель - используйте флаг CRYPT_VERIFYCONTEXT в первом вызове CryptAcquireContext | ||||
| ||||
Да спасибо, так работет, но снова возникли вопросы - после второго вызова CryptAcquireContext возникает на некоторое время UI с носителями и автоматом потом исчезает (вызов с ключом NULL, с CRYPT_SILENT возращается ошибка) - можно поборть возникновение этого окошка? И второй вопрос - как однозначно определить, что этот контейнер принадлежит не реестру, а какому-либо носителю? | ||||
| ||||
Вам поможет вызов PP_ENUMCONTAINERS c флагом CRYPT_FQCN = 0x10 (Fully Qualified Container Name) - решится и первая и вторая проблема | ||||
| ||||
Какой-то недокументированный ключ, но он помог со второй проблемой. Первая же проблема остается (после передачи полного имени конейнера, т.е. с SCARD\etc). Как я говорил, я пытался использовать ключ CRYPT_SILENT, но в МСДН есть такая ремарка: The application requests that the CSP not display any user interface (UI) for this context. If the CSP must display the UI to operate, the call fails and the NTE_SILENT_CONTEXT error code is set as the last error. Может, ваш CSP не может не отображать это окно? | ||||
| ||||
А без CRYPT_SILENT какое окно отображается? Случайно не ввода пина? | ||||
| ||||
Контекст просто не инициализируется с этим ключем. Кстати, я посмотрел - если с помощью средств самого провайдера смотреть сертификаты в контейнере - окошко тоже всплывает. Т.е. сервис-просмотреть сертификаты в контейнере и дальше. Окошко появляется. И еще вопрос - я получаю pCertContext, могу с его помощью шифровать, но подписывать не могу, т.к. не может найти закрытый ключ (функция CertGetCertificateContextProperty). Надо использовать функции более низкого уровня для подписывания? Но как же тогда быть с операцией подписывание/шифрование? | ||||
| ||||
Насчет подписания разобрался, да, использовать функции более низного уровня. Подписание/шифрование работает нормально... А вот насчет проверки еще не знаю, т.к. какое ей подсовывать хранилище? Я насчет функции CryptDecryptAndVerifyMessageSignature. | ||||