| ||||
| ||||
При получении сертификатов хранимых в контейнерах, находящихся на eToken-е натолкнулся на особенность работы с контейнерами: Контейнеры созданные с помощью CSP 2.0 при вызове CPGetUserKey() выводят UI c запросом PIN-кода Контейнеры созданные с помощью CSP 3.0 подобных запросов не выводят. Подскажите, пожалуйста, существует ли программный способ определения нужно ли вызывать CPSetProvParam(hProv,PP_SIGNATURE_PIN,pPIN,0) перед CPGetUserKey(hProv,AT_SIGNATURE,phUserKey) Чтобы UI c запросом PIN-кода не выводился. Заранее спасибо. | ||||
Ответы: | ||||
| ||||
Вообще-то CSP, на котором делали контейнер, не должен иметь значения. Влияет версия CSP, на котором открывается контейнер. Для 3.0 больше операций не требуют ПИНа. Для того, чтобы не было UI - используйте флажок CRYPT_SILENT и FQCN-имя контейнера в ф-и ..AcquireContext. Тогда, при соответствующей ошибке функции работы с ключами (0x8010006B) можно понять, нужно ли задавать ПИН - и задать его программно или переоткрыть контейнер и спросить ПИН у пользователя. | ||||
| ||||
К сожалению описанный Вами способ не сработал под CryptoPro 3.0 для контейнера созданного CSP 2.0 при вызове функции CPGetUserKey(...) без задания PIN-кода, возвращается FALSE, а код ошибки, получаемый функцией GetLastError() всегда 0x8009000D (NTE_NO_KEY), в независимости есть ключ или нет. Хочется узнать есть ли какой-нибудь программный способ определить какой версией CSP был создан контейнер ? | ||||
| ||||
Можно уточнить - это при открытии контекста с флажком CRYPT_SILENT ? А без него - работает? | ||||
| ||||
Да, ошибка возникает при открытии контекста с флагом CRYPT_SILENT. Если этот флаг не указывать то при вызове CPGetUserKey(...) поднимается UI c запросом PIN-кода - если PIN-код ввести правильно все проходит хорошо, если PIN-код неверный возвращается ошибка 0x8009000D (NTE_NO_KEY). Есть ли способ определить какой версией CSP был создан контейнер ? | ||||
| ||||
Отличие контейнеров, созданных версией CSP 3 от 2 в том, что файл \e00e\0b00\CCxx\f003 (аналог "header.key") в случае 3-й версии не требует ПИН (Public binary file). Именно в нём хранится сертификат (если он есть в контейнере). Собственно, так и было задумано. Может, Вам поступить проще - всегда сначала задавать ПИН программно, а если операция требует ПИНа и обломается из-за того, что ПИН неверный - то спросить его через UI. | ||||
| ||||
Спасибо, за информацию о расположении данных в контейнере, действительно все так, как Вы написали. Но предлагаемый способ так же не сработал. под CryptoPro 3.0 для контейнера созданного CSP 2.0 при вызове функции CPGetUserKey(...) с установленным неверным PIN-кодом, возвращается FALSE, а код ошибки, получаемый функцией GetLastError() всегда 0x8009000D (NTE_NO_KEY), в независимости есть ключ или нет. Если нет возможности узнать, кем был создан контейнер придется без установки PIN-кода вызывать подряд CPGetUserKey(..AT_SIGNATURE..) CPGetUserKey(.AT_KEYEXCHANGE..) и если оба вызова не увенчаются успехом спрашивать у пользователя PIN-код, выставлять его и повторять попытку получения ключа еще раз. Хочется понять будет ли выполнять CryptoPro логин на токен, когда вызывается CPGetUserKey(...) без установленного PIN-кода ? Так как количество веденных неверно PIN-кодов на eToken-ах обычно ограничивается. | ||||
| ||||
Чтобы совсем всё было правильно, конечно, нужен конвертер ключевых контейнеров на токене, который бы снимал требование ПИН-кода при доступе к этому файлу. Поскольку именно на этом уровне самим токеном определяется, что ПИН нужен. А поскольку CSP 3 считает, что в этом случае (GetUserKey) ПИН не должен спрашиваться, то он и не кмеет выставить правильную ошибку, и говорит, что ключа нет совсем. Так что, придётся спрашивать ПИН у пользователя для контейнеров, сделанных на 2.0. | ||||