Ключевое слово в защите информации
КЛЮЧЕВОЕ СЛОВО
в защите информации
Получить ГОСТ TLS-сертификат для домена (SSL-сертификат)
Добро пожаловать, Гость! Чтобы использовать все возможности Вход или Регистрация.

Уведомление

Icon
Error

2 Страницы12>
Опции
К последнему сообщению К первому непрочитанному
Offline ssladkov  
#1 Оставлено : 15 сентября 2010 г. 7:09:58(UTC)
ssladkov

Статус: Участник

Группы: Участники
Зарегистрирован: 15.09.2010(UTC)
Сообщений: 19
Мужчина
Откуда: Москва

Использую флаг CRYPT_ACQUIRE_CACHE_FLAG для кэширования провайдера и ключей.
Но по истечению таймаута пытаюсь сбросить установленное свойство.
Но получение провайдера при помощи CryptAcquireCertificatePrivateKey проходит успешно,
даже если вынут контейнер с ключами, т.е. кэш не очищается

Код:
        // Проверяем нужно ли убрать из кэша провайдер
        if (::GetTickCount() - lastTick > config.GetLastOperationKeyTimeout()*1000)
            // Убираем закэшированный провайдер из сертификата
            if (!::CertSetCertificateContextProperty(SignerCert.GetContext(), 
                CERT_KEY_CONTEXT_PROP_ID, 0, 0))
                throw WinApiException();

        DWORD dwFlags = CRYPT_ACQUIRE_CACHE_FLAG; // кэшируем        
        BOOL fCallerFreeProv;

        if (!::CryptAcquireCertificatePrivateKey(SignerCert.GetContext(),
            /* сверяем открытый ключ с ключом сертификата */CRYPT_ACQUIRE_COMPARE_KEY_FLAG |
            dwFlags, 0, &hProv, &dwKeySpec, &fCallerFreeProv))
        {
           // Пробуем другой способ получить провайдер
           ...
        }
        // При повторном вызове ошибки не будет даже если таймаут исчез и контейнер вынут



Что неправильно? Заранее спасибо.

Отредактировано пользователем 15 сентября 2010 г. 7:13:24(UTC)  | Причина: Не указана

Offline Максим Коллегин  
#2 Оставлено : 15 сентября 2010 г. 12:40:48(UTC)
Максим Коллегин

Статус: Сотрудник

Группы: Администраторы
Зарегистрирован: 12.12.2007(UTC)
Сообщений: 6,393
Мужчина
Откуда: КРИПТО-ПРО

Сказал «Спасибо»: 37 раз
Поблагодарили: 717 раз в 621 постах
Кроме кэша в CryptoAPI, есть еще кэширование контекстов в криптопровайдере. Если оно специально не включено (сервис и чекбокс в панели управления), то контейнер в кэше до закрытия последнего контекста с ним.
Знания в базе знаний, поддержка в техподдержке
Offline ssladkov  
#3 Оставлено : 15 сентября 2010 г. 17:35:14(UTC)
ssladkov

Статус: Участник

Группы: Участники
Зарегистрирован: 15.09.2010(UTC)
Сообщений: 19
Мужчина
Откуда: Москва

maxdm написал:
Кроме кэша в CryptoAPI, есть еще кэширование контекстов в криптопровайдере. Если оно специально не включено (сервис и чекбокс в панели управления), то контейнер в кэше до закрытия последнего контекста с ним.


Кэширование контекстов в криптопровайдере специально не включал.
Откуда тогда CryptAcquireCertificatePrivateKey берет закешированный провайдер,
если свойство CERT_KEY_CONTEXT_PROP_ID сбрасывается?

То есть получается, что если провайдер, который был асоциирован с сертификатом
не освободился, то он всеравно как-то находится ф-цией CryptAcquireCertificatePrivateKey,
несмотря на сброс CERT_KEY_CONTEXT_PROP_ID? Если так, то это очень плохо и
как избежать данной ситуации?
Offline Максим Коллегин  
#4 Оставлено : 15 сентября 2010 г. 17:38:50(UTC)
Максим Коллегин

Статус: Сотрудник

Группы: Администраторы
Зарегистрирован: 12.12.2007(UTC)
Сообщений: 6,393
Мужчина
Откуда: КРИПТО-ПРО

Сказал «Спасибо»: 37 раз
Поблагодарили: 717 раз в 621 постах
закрывать открытый CryptAcquireCertificatePrivateKey контекст.
Знания в базе знаний, поддержка в техподдержке
Offline ssladkov  
#5 Оставлено : 15 сентября 2010 г. 23:35:34(UTC)
ssladkov

Статус: Участник

Группы: Участники
Зарегистрирован: 15.09.2010(UTC)
Сообщений: 19
Мужчина
Откуда: Москва

maxdm написал:
закрывать открытый CryptAcquireCertificatePrivateKey контекст.


К сожалению ваши ответы для меня ситуацию не прояснили.

Итак
1) CryptAcquireCertificatePrivateKey вызывается с флагом CRYPT_ACQUIRE_CACHE_FLAG и возвращает out параметр fCallerFreeProv == FALSE, что означает, что вызывающая сторона не должна освобождать провайдер.
Разве сброс свойства CERT_KEY_CONTEXT_PROP_ID перед следующим вызовом CryptAcquireCertificatePrivateKey не освобождает закэшированный провайдер? Как тогда его закрывать?

2) Из ваших слов я понял, что даже если провайдер был получен ранее для этого сертификата, то при вызове еще одного CryptAcquireCertificatePrivateKey возвращается первый провайдер с закэшированными ключами. Это так? Если да, то такое поведение свойственено только криптопро? В документации MSDN написано только про кэширование в CERT_KEY_CONTEXT_PROP_ID и больше не говорится о неявном кэше провайдера.
Offline Максим Коллегин  
#6 Оставлено : 15 сентября 2010 г. 23:52:09(UTC)
Максим Коллегин

Статус: Сотрудник

Группы: Администраторы
Зарегистрирован: 12.12.2007(UTC)
Сообщений: 6,393
Мужчина
Откуда: КРИПТО-ПРО

Сказал «Спасибо»: 37 раз
Поблагодарили: 717 раз в 621 постах
Я все написал в первом ответе. CERT_KEY_CONTEXT_PROP_ID не имеет никакого отношения к кэшу контейнеров - это API верхнего уровня.
Знания в базе знаний, поддержка в техподдержке
Offline ssladkov  
#7 Оставлено : 16 сентября 2010 г. 0:34:33(UTC)
ssladkov

Статус: Участник

Группы: Участники
Зарегистрирован: 15.09.2010(UTC)
Сообщений: 19
Мужчина
Откуда: Москва

maxdm написал:
Я все написал в первом ответе. CERT_KEY_CONTEXT_PROP_ID не имеет никакого отношения к кэшу контейнеров - это API верхнего уровня.


Я попробую еще раз. В самом простом случае не работает

CryptAcquireCertificatePrivateKey вызывается с флагом CRYPT_ACQUIRE_CACHE_FLAG и возвращает out параметр fCallerFreeProv == FALSE, что означает, что вызывающая сторона не должна освобождать провайдер. (из МСДН)
Я его и не закрываю. Но по истечению таймаута мне нужно, чтобы кэш пропал. Я его пытаюсь сбросить
установкой свойства CERT_KEY_CONTEXT_PROP_ID, но не получается.
Каким способом, тогда мне закрыть провайдер? Вытащить из сертификата и явно закрыть?
Offline Максим Коллегин  
#8 Оставлено : 16 сентября 2010 г. 2:32:33(UTC)
Максим Коллегин

Статус: Сотрудник

Группы: Администраторы
Зарегистрирован: 12.12.2007(UTC)
Сообщений: 6,393
Мужчина
Откуда: КРИПТО-ПРО

Сказал «Спасибо»: 37 раз
Поблагодарили: 717 раз в 621 постах
Про pfCallerFreeProvOrNCryptKey был неправ.
Для удаления из кэша достаточно закрыть контекст сертификата - все по тому же MSDN.

Отредактировано пользователем 16 сентября 2010 г. 12:51:55(UTC)  | Причина: Не указана

Знания в базе знаний, поддержка в техподдержке
Offline Максим Коллегин  
#9 Оставлено : 16 сентября 2010 г. 12:58:39(UTC)
Максим Коллегин

Статус: Сотрудник

Группы: Администраторы
Зарегистрирован: 12.12.2007(UTC)
Сообщений: 6,393
Мужчина
Откуда: КРИПТО-ПРО

Сказал «Спасибо»: 37 раз
Поблагодарили: 717 раз в 621 постах
Провел эксперимент - освобождения контекста сертификата недостаточно - нужно закрывать хранилище, содержащее сертификат.
Так что MSDN обманывает, во всяком случае на Win 7
Знания в базе знаний, поддержка в техподдержке
Offline ssladkov  
#10 Оставлено : 16 сентября 2010 г. 16:59:34(UTC)
ssladkov

Статус: Участник

Группы: Участники
Зарегистрирован: 15.09.2010(UTC)
Сообщений: 19
Мужчина
Откуда: Москва

У меня не используется хранилище для сертификатов. Он создается в памяти (читается из базы данных) и контекст сохраняется в течении жизни программы. Но пока освобождение контекста сертификата еще не пробовал. Но даже если это и будет работать, чтобы прекратить кэширование придется освободить контекст и создать сертификат заново. Еще экспериментировал со свойством CERT_KEY_PROV_HANDLE_PROP_ID, при сбросе которого МСДН обещает освободить закэшированного провайдера, но ничего не вышло.
Если можно, еще два вопроса:
1) CryptAcquireCertificatePrivateKey возвращает мне каждый раз разный хэндл провайдера. Означает ли это что объект провайдера действительно разный и проблема не из-за того, что каждый раз используется закэшированный провайдер, а из-за того, что крипто-про кэширует ключевой контейнер, так как виндоуз не закрыл закэшированный по началу провайдер.

2) Есть ли возможность изменить поведение крипто-про, чтобы он перестал кэшировать ключевой контейнер глобально, а скажем кэшировал в рамках только одного экземпляра провайдера? Ведь ошибка в коде или в крипто-апи виндоуз, вызывающая утечку провайдера, ведет к большой дыре в безопасности. Так пользователь может вынуть ключевой контейнер и отойти от рабочего места, а в это время кто угодно может подписать за него документы.
RSS Лента  Atom Лента
Пользователи, просматривающие эту тему
Guest
2 Страницы12>
Быстрый переход  
Вы не можете создавать новые темы в этом форуме.
Вы не можете отвечать в этом форуме.
Вы не можете удалять Ваши сообщения в этом форуме.
Вы не можете редактировать Ваши сообщения в этом форуме.
Вы не можете создавать опросы в этом форуме.
Вы не можете голосовать в этом форуме.