| ||||
| ||||
Добрый день! На IIS 5 работает Web-service, осуществляющий подпись данных. Служба по файлу сертификата (cer) получает закрытый ключ с помощью функции CryptAcquireCertificatePrivateKey и этим ключем производит подпись. Контейнер закрытых ключей скопирован в реестр, данный сертификат находится в Personal пользователя под которым работает IIS. Проблема в том, что при подписи производится обращение к флоппи. Если там есть дискета с закрытым ключем - подпись происходит нормально, иначе возникает ошибка 80100069 (насколько я понял, информирующая о извлечении ключевого носителя). В реесте поиск закрытых ключей по всей видимости не происходит. Как скопировать контейнер закрытого ключа с дискеты в реестр и куда установить сертификат, чтобы ключ брался из реестра и не было обращений в дисководу? | ||||
Ответы: | ||||
| ||||
Рекомендую такой алгоритм, без обращения к CryptAcquireCertificatePrivateKey для сертификата из файла, т.к. эта функция работает с кэшем а средств для его очистки нет. 0)Если у сертификата IIS, который установлен в хранилише пользователя нет ссылки на секретный ключ, то делаете ее с помощью контрольной панели (однократная операция) 1)Читаете из файла сертификат и по нему находите нужный в Personal. 2)У сертификата их хранилища читаете CertGetCertificateContextProperty(CERT_KEY_PROV_INFO_PROP_ID), по нему уже открываете контейнер с помощью CryptAcquireContext. | ||||
| ||||
> Служба по файлу сертификата (cer) получает закрытый ключ... Это абсолютно неправильно. В файле сертификата нет ссылки на закрытый ключ. То, что это работает (при условии, что сертификат установлен в хранилище Personal с привязкой к ключу) - это недокументированная особенность CryptoAPI. Правильно открывать хранилище (CertOpenStore) и искать сертификат в хранилище (CertFindCertificateInStore) и потом уже CryptAcquireCertificatePrivateKey. Тогда гарантированно будет найден тот ключевой контейнер, который был указан при установке сертификата в хранилище Личные. Скопировать контейнер можно, если при создании оригинального контейнера был выставлен флаг, разрешающий это действие. (Панель управления - КриптоПро CSP - Сервис - Скопировать контейнер). Установка сертификата: Панель управления - КриптоПро CSP - Сервис - Установить личный сертификат | ||||
| ||||
Kirill, Василий, спасибо за исчерпывающие ответы! Буду пробывать, напишу о результате. | ||||
| ||||
хех, попробывал. Не работает ((( Делаю так. Беру файл сертификата. Получаю его контекст с помощью CertCreateCertificateContext. Получаю контекст криптопровайдера и хранилища сертификатов с закрытыми ключами: CryptAcquireContext(ref hCryptProv, null, null, 75, CRYPT_VERIFYCONTEXT); ... CertOpenSystemStore(hCryptProv, "MY"); Провожу поиск сертфиката в хранилище CertFindCertificateInStore(hCertStore, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, CERT_FIND_EXISTING, pSenderCertContextFromFile, IntPtr.Zero); Т.е. пытаюсь получить контекст сертификата из хранилища, соответствующий сертификату из файла. Вот на этом шаге и возникают проблемы. Приложение, запущенное пользователем у котого в Personal установлен сертификат с закрытым ключем отрабатывает прекресно - сертификат в хранилище находится, его контектст получает, далее удается сделать все что нужно. Web-служба работающая на IIS через ананимный доступ от _этого_ же пользователя сертификат в хранилище найти не может. В чем может быть дело, что я делаю не так? Вопрос наверно не из простых, но все же помогите пожалуйста разобраться. Спасибо! | ||||
| ||||
IIS работает не из-под простого пользователя. Для 2003 это специальная учётная запись - NETWORK SERVICE. Как правило, для служб сертификат ставится в хранилище "Личные" локального компьютера, а не пользователя. | ||||
| ||||
Пробывал и в Computer/Personal ставить. Результат тот же. IIS 5.1 WinXP SP2. Работает под моей учетной администраторской учетной записью. Приложения, использующие крипто прогоняю под ней же, в них все работает. Почему же из под IIS не находит сертификат в хранилище?.. ( | ||||
| ||||
> Пробывал и в Computer/Personal ставить. Результат тот же. Вопрос - при этом при открытии хранилища указывали, что теперь это хранилище компьютера? | ||||
| ||||
Перепробывал уже кажется все, во всех вариациях. Не работает. Получаю контекст криптопровайдера так: CryptAcquireContext(ref hCryptProv, null, null, 75, CRYPT_VERIFYCONTEXT) Хранилище пробывал открывать так: CertOpenSystemStore(hCryptProv, "MY"); Открывается. Но при вызове CertFindCertificateInStore по контексту сертификата из файла результат - ошибка 80092004 - CRYPT_E_NOT_FOUND "CRYPT_E_NOT_FOUND". Сертификат установлен в Personal User'а (от которого работает IIS) и в Computer/Personal. Привязки к закрытым ключам есть везде. Контейнеры закрытых ключей опять же есть в реесте и User и в Computer. Если же открываю хранилище через CertOpenStore(9, 0, 0, CERT_SYSTEM_STORE_LOCAL_MACHINE, "MY") возращается null и LastError = 5, что как я понимаю значит ERROR_ACCESS_DENIED. Пробывал открывать через CertOpenStore гм... с разными аргументами. Открывает только для CERT_SYSTEM_STORE_CURRENT_USER, и опять же потом в хранилище сертификат не находится. Вся странность, как я уже писал, заключается в том, что этот код не работает из Web-сервиса под IIS при анонимном доступе, используется аккаунт администратора компьютера. Приложения, использующие тот же код запущенные тем же пользователем нормально работают. Т.е. CertOpenStore(9, 0, 0, CERT_SYSTEM_STORE_LOCAL_MACHINE, "MY") возвращает нормальный хендл хранилища, и контекст нужного мне сертификата там находится. Куда копать? | ||||
| ||||
1. Если Вы вызываете CryptAcquireContext(...), а ключ в хранилище компьютера, то нужно добавить флажок CRYPT_MACHINEKEYSET. 2. Можно уточнить - в "Диспетчере служб IIS" в Свойствах веб-узла (или каталога) - Безопасность каталога - верхняя кнопка Изменить - какие сейчас галки? Если есть галка "Анонимный доступ" - то по нажатию Изменить на ней - Вы вручную заменили аккаунт по умолчанию на "Администратор"(или имя пользователя Win с правами админа) и ввели правильный пароль и подтверждение (и перезапустили IIS)? | ||||
| ||||
1. Добавил. Результат тот же. 2. Стоит только галка "Анонимный доступ". Да, вручную задавал login/password административной учетной записи. Причем, даже создавал нового админа, ставил ему сертификат в Personal, из под него же ставил в Computer/Personal. Не урезает ли IIS какие либо параметры учетной записи при анонимном доступе? Тот же Context.User.Identity.Name WebService выдает как "" а не "Administrator", может где-то тут подвох. Под Web сервером от Visual Web Developer 2005 EE все нормально работает. А вот IIS...( | ||||
| ||||
Возможно стоит сбросить вам мой код на mail (какой?), так проще будет? | ||||
| ||||
Заработало! Проблема была в ограничениях ASPNET. Посоветовали подправить machine.config - помогло :) | ||||
| ||||
Если не сложно, напишите здесь подробности, чтобы решение имелось в этой теме. | ||||
| ||||
Сам пока толком не разбирался, просто сделал как посоветовали - помогло. http://www.aspnetmania.com/Forums/ForumMessage/327925.html http://forum.codeby.net/topic15488.html | ||||