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

Уведомление

Icon
Error

Опции
К последнему сообщению К первому непрочитанному
Offline AndreyM  
#1 Оставлено : 15 февраля 2008 г. 1:27:32(UTC)
AndreyM

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

Группы: Участники
Зарегистрирован: 15.02.2008(UTC)
Сообщений: 11

подскажите пожалуйста как найти все подходящие сертификаты получателей, если известно какой криптопровайдер и алгоритм шифрования?

Отредактировано пользователем 15 февраля 2008 г. 1:29:05(UTC)  | Причина: Не указана

Offline Kirill Sobolev  
#2 Оставлено : 15 февраля 2008 г. 14:39:28(UTC)
Кирилл Соболев

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

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

Поблагодарили: 177 раз в 168 постах
Можно узнать, какой алгоритм ОК поддерживает криптопровайдер, найти все сертификаты с этим алгоритмом и выбрать из них такий, где в расширение "Использование ключа" прописано "Шифрование данных, шифрование ключей".
Техническую поддержку оказываем тут
Наша база знаний
Offline AndreyM  
#3 Оставлено : 22 февраля 2008 г. 4:05:54(UTC)
AndreyM

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

Группы: Участники
Зарегистрирован: 15.02.2008(UTC)
Сообщений: 11

спасибо за ответ :) а не подскажете еще по одному вопросу:

для подписи сертификат как найти? знаю что у сертификата должна быть ссылка на закрытый ключ, но вот как проверить что она есть...
Offline Kirill Sobolev  
#4 Оставлено : 22 февраля 2008 г. 14:25:47(UTC)
Кирилл Соболев

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

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

Поблагодарили: 177 раз в 168 постах
CertGetCertificateContextProperty(.., CERT_KEY_PROV_INFO_PROP_ID, ..)
если эта функция вернет ошибку - значит ссылки на секретный ключ нет.
Техническую поддержку оказываем тут
Наша база знаний
Offline Дмитрий Жигулин  
#5 Оставлено : 22 февраля 2008 г. 19:35:27(UTC)
Дмитрий Жигулин

Статус: Новичок

Группы: Участники
Зарегистрирован: 21.02.2008(UTC)
Сообщений: 5
Откуда: Донецк

Kirill Sobolev написал:
CertGetCertificateContextProperty(.., CERT_KEY_PROV_INFO_PROP_ID, ..)
если эта функция вернет ошибку - значит ссылки на секретный ключ нет.


А как же CryptFindCertificateKeyProvInfo?
Offline Kirill Sobolev  
#6 Оставлено : 22 февраля 2008 г. 20:33:01(UTC)
Кирилл Соболев

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

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

Поблагодарили: 177 раз в 168 постах
Эта функция ищет контейнер, который соотвествует открытому ключу в сертификате, но не отвечает на вопрос, есть ли у конкретного сертификата ссылка на контейнер с секретным ключем.
Техническую поддержку оказываем тут
Наша база знаний
Offline Дмитрий Жигулин  
#7 Оставлено : 24 февраля 2008 г. 14:40:34(UTC)
Дмитрий Жигулин

Статус: Новичок

Группы: Участники
Зарегистрирован: 21.02.2008(UTC)
Сообщений: 5
Откуда: Донецк

Kirill Sobolev написал:
Эта функция ищет контейнер, который соотвествует открытому ключу в сертификате, но не отвечает на вопрос, есть ли у конкретного сертификата ссылка на контейнер с секретным ключем.


:) Контейнер - это привязка секретного ключа к сертификату. Не может быть разных контейнеров для публичного и приватного ключей.

Контейнер идентифицируется по имени. Для сертификата с приватным ключем достраточно установть сетификату ContextPorperty, где указать имя провайдера и имя контейнера. Но это ещё не значит, что этот контейнер реально существует и соответствует сертификату. CertGetCertificateContextProperty в данном случае не вернет ошибки.

СryptFindCertificateKeyProvInfo выполнит намного больше работы.

Сначала функция проверит что контейнер указанный в сертификате реально существует, для этого вызвовет CryptAcquireCertificatePrivateKey (где запросит ContextProperty у сертификата, откуда получит имя провайдера и имя контейнера и затем выполнит CryptAcquireContext).

Потом удостоверится, что публичный ключ сертификата соответствует публичному ключу ключевой пары контейнера, а не выпонены какие либо компроментирующие контейнер манипуляции как указано выше. Для этого у провайдера будет получен публичный ключ через CryptExportKey и сравнен с публичным ключем сертификата.

Может что-то упустил, но в общих чертах так.
Offline AndreyM  
#8 Оставлено : 24 февраля 2008 г. 15:38:40(UTC)
AndreyM

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

Группы: Участники
Зарегистрирован: 15.02.2008(UTC)
Сообщений: 11

Дмитрий Жигулин написал:
Сначала функция проверит что контейнер указанный в сертификате реально существует, для этого вызвовет CryptAcquireCertificatePrivateKey (где запросит ContextProperty у сертификата, откуда получит имя провайдера и имя контейнера и затем выполнит CryptAcquireContext).


а когда функция будет вызывать CryptAcquireContext то ведь она требует пароль к контейнеру. Это получается, если я буду перебирать сертификаты в хранилище, то для каждого сертификата у пользователя будет пароль спрашиваться?

И чтобы не создавать новую тему еще один вопрос:
Получаю список алгоритмов, поддерживаемых криптопровайдером с помощью CryptGetProvParam с параметром PP_ENUMALGS_EX. Как определить какие алгоритмы подходят для шифрования данных, а какие нет?

Отредактировано пользователем 25 февраля 2008 г. 0:22:02(UTC)  | Причина: Не указана

Offline Дмитрий Жигулин  
#9 Оставлено : 25 февраля 2008 г. 15:41:47(UTC)
Дмитрий Жигулин

Статус: Новичок

Группы: Участники
Зарегистрирован: 21.02.2008(UTC)
Сообщений: 5
Откуда: Донецк

Цитата:
а когда функция будет вызывать CryptAcquireContext то ведь она требует пароль к контейнеру.

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

Цитата:
Это получается, если я буду перебирать сертификаты в хранилище, то для каждого сертификата у пользователя будет пароль спрашиваться?

Пароль авторизирует пользователя на весь период сессии работы с провайдером. Кроме этого виндовое хранилище и криптопровайдер это вообще то разные сущности :).

Цитата:
И чтобы не создавать новую тему еще один вопрос:
Получаю список алгоритмов, поддерживаемых криптопровайдером с помощью CryptGetProvParam с параметром PP_ENUMALGS_EX. Как определить какие алгоритмы подходят для шифрования данных, а какие нет?

Вообще в msdn - е есть описание алгоритмов, а для автоматизации можно попробовать CryptFindOIDInfo и посмотреть какой у алгоритма dwGroupId.
Offline AndreyM  
#10 Оставлено : 25 февраля 2008 г. 21:55:03(UTC)
AndreyM

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

Группы: Участники
Зарегистрирован: 15.02.2008(UTC)
Сообщений: 11

что-то я совсем совсем запутался в каком порядке и откуда получить сертификат получателя, ссылку на криптопровайдер и алгоритм шифрования.

Исходно целью было зашифровать массив байтов с помощью функции CryptEncryptMessage. Ей нужно передать массив сертификатов (у меня это просто массив из одного сертификата, который выбрал пользователь), а также надо передать структуру CRYPT_ENCRYPT_MESSAGE_PARA в которой содержится HCRYPTPROV, который должен соответствовать сертификату и еще надо указать OID алгоритма в структуре CRYPT_ALGORITHM_IDENTIFIER. И вот у меня сложность в каком порядке спрашивать эти данные у пользователя и как определять возможные варианты. Например если сначала просим пользователя выбрать сертификат, то как потом показать ему список криптопровайдеров которыми он сможет зашифровать данные этим сертификатом. И плюс еще нужно каким-то образом выбрать алгоритм. А то у меня если сертификат не соответствует криптопровайдеру или алгоритм указан выскакивает ошибка "Неизвестный криптографический алгоритм".

Смотрел примеры из МСДН так там вообще берут криптопровайдер по-умолчанию, алгоритм выбирают szOID_RSA_RC4 и сертификат тоже первый попавшийся. А вот как сделать чтобы эти три параметра друг другу соответствовали не могу найти.

Еще попробовал брать алгоритм из сертификата EncryptAlgorithm.pszObjId = pRecipientCert->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId - на тестовом сертификате крипто-про шифрование сработало, а на другом сертификате с RSA ключем вывалилась ошибка "Неизвестный криптографический алгоритм". Так что теперь вообще не знаю откуда выбрать алгоритм, который будет точно известным. Из сертификата не получается, из криптопровайдера можно получить только все поддерживаемые алгоритмы и как из них выбрать тоже не понятно.

В МСДН'е все так просто в примере, один вызов функции и зашифровано :) А на практике вон сколько предварительно нужно всяких данных собрать d'oh!
Offline Максим Коллегин  
#11 Оставлено : 26 февраля 2008 г. 0:14:53(UTC)
Максим Коллегин

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

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

Сказал «Спасибо»: 19 раз
Поблагодарили: 613 раз в 546 постах
хм
Цитата:

CRYPT_ENCRYPT_MESSAGE_PARA Structure
....
hCryptProv
This member is not used and should be set to NULL.
Знания в базе знаний, поддержка в техподдержке
Offline AndreyM  
#12 Оставлено : 26 февраля 2008 г. 0:38:07(UTC)
AndreyM

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

Группы: Участники
Зарегистрирован: 15.02.2008(UTC)
Сообщений: 11

maxdm написал:

CRYPT_ENCRYPT_MESSAGE_PARA Structure
....
hCryptProv
This member is not used and should be set to NULL.


странно, все описания смотрю в локальном мсдн, который вместе со студией ставится. там этой строчке нет. а сейчас посмотрел в онлайновой версии. действительно так написано. но тогда вопрос как функция CeryptEncryptMessage узнает каким криптопровайдером шифровать сообщение? Из сертификата по-моему она такую информацию не достанет. В любом случае попробую передавать NULL и напишу что получилось.
Offline AndreyM  
#13 Оставлено : 26 февраля 2008 г. 1:41:04(UTC)
AndreyM

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

Группы: Участники
Зарегистрирован: 15.02.2008(UTC)
Сообщений: 11

передаю NULL - работает :) проверил на сертификате с ГОСТом и с RSA. а как тогда правильно, имея только сертификат, определить какой OID алгоритма использовать в структуре CRYPT_ALGORITHM_IDENTIFIER ?
Offline Kirill Sobolev  
#14 Оставлено : 26 февраля 2008 г. 15:21:03(UTC)
Кирилл Соболев

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

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

Поблагодарили: 177 раз в 168 постах
Цитата:
Контейнер - это привязка секретного ключа к сертификату

Нет. Контейнер - это объект для хранения ключевой информации. Сертификат - это связь ОК с текстовой строкой. Вообщем то это 2 независимых объекта, вот для того чтоб их связать можно сертификату прописать ссылку на контейнер секретного ключа. Можно связать наоборот - в контейнер записать сертификат.
Цитата:
CertGetCertificateContextProperty в данном случае не вернет ошибки.

Да, ошибка вылезет в момент создания подписи, вернее не ошибка а предложение указать нужный контейнер. А вот такой вопрос - CryptAcquireCertificatePrivateKey нормально работает с сертификатам, у которых ссылки на секретный ключ нет (например сертификат прочитан из файла), а смогут ли высокоуровневые фунции подписи сделаь тоже самое?
Цитата:
в осталных случаях провайдер не должен этого делать.

В идеале конечно. Но иногда провайдеру просто неоткуда взять ОК, кроме как вычислить его из секретного.
Цитата:
как тогда правильно, имея только сертификат, определить какой OID алгоритма использовать в структуре CRYPT_ALGORITHM_IDENTIFIER

Надо смотреть какие алгоритмы поддерживает CSP - CryptGetProvParam(.., PP_ENUMALGS, ..)
Техническую поддержку оказываем тут
Наша база знаний
Offline AndreyM  
#15 Оставлено : 26 февраля 2008 г. 16:16:47(UTC)
AndreyM

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

Группы: Участники
Зарегистрирован: 15.02.2008(UTC)
Сообщений: 11

Конкретно для Крипто-про в CRYPT_ALGORITHM_IDENTIFIER.pszObjId похоже можно вообще передавать любую строку, даже просто "" работает :)

Отредактировано пользователем 26 февраля 2008 г. 16:17:38(UTC)  | Причина: Не указана

Offline Kirill Sobolev  
#16 Оставлено : 26 февраля 2008 г. 17:07:40(UTC)
Кирилл Соболев

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

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

Поблагодарили: 177 раз в 168 постах
Работает :) Но сделано это было не от хорошей жизни и тем более не является правильным способом задания алгоритма шифрования в общем случае.
Техническую поддержку оказываем тут
Наша база знаний
Offline Дмитрий Жигулин  
#17 Оставлено : 26 февраля 2008 г. 20:22:29(UTC)
Дмитрий Жигулин

Статус: Новичок

Группы: Участники
Зарегистрирован: 21.02.2008(UTC)
Сообщений: 5
Откуда: Донецк

Цитата:
Да, ошибка вылезет в момент создания подписи, вернее не ошибка а предложение указать нужный контейнер. А вот такой вопрос - CryptAcquireCertificatePrivateKey нормально работает с сертификатам, у которых ссылки на секретный ключ нет (например сертификат прочитан из файла), а смогут ли высокоуровневые фунции подписи сделаь тоже самое?

1. Откуда бедный пользователь узнает имя контейнера :) , ему вообще быть достаточно ключика на сертификате и знания пин кода.
2. CryptAcquireCertificatePrivateKey не будет работать с сертификатом без приватного ключа, это должно быть понятно из её названия.
3. CryptAcquireCertificatePrivateKey - это и есть высокоуровенвая функция, она напрямую в провайдере не реализуется.

Цитата:
Нет. Контейнер - это объект для хранения ключевой информации. Сертификат - это связь ОК с текстовой строкой. Вообщем то это 2 независимых объекта, вот для того чтоб их связать можно сертификату прописать ссылку на контейнер секретного ключа. Можно связать наоборот - в контейнер записать сертификат.

Цитата:

В идеале конечно. Но иногда провайдеру просто неоткуда взять ОК, кроме как вычислить его из секретного.

мда...
Offline Kirill Sobolev  
#18 Оставлено : 26 февраля 2008 г. 21:26:20(UTC)
Кирилл Соболев

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

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

Поблагодарили: 177 раз в 168 постах
1. Имя контейнера знать придется все равно. Даже функция CryptFindCertificateKeyProvInfo не подключит контейнер, если вдруг его нет в системе.
2. Тем не менее, работает, несмотря на название. И иногда возникают некоторые неприятные эффекты.
3. Это безусловно высокоуровневая функция, но она никак не реализует операцию подписи.
Техническую поддержку оказываем тут
Наша база знаний
Offline Юрий  
#19 Оставлено : 27 февраля 2008 г. 13:57:24(UTC)
Юрий

Статус: Активный участник

Группы: Участники
Зарегистрирован: 22.01.2008(UTC)
Сообщений: 671
Мужчина
Российская Федерация
Откуда: Йошкар-Ола

Сказал «Спасибо»: 3 раз
Поблагодарили: 93 раз в 67 постах
К AndreyM: стоит задача зашифровать данные с использованием сертификатов.

Первично необходимо сказать, что сертификат должен быть из хранилища сертификатов "My" (Personal). В теории, конечно, привязку ключевого контейнера можно сделать к сертификату в любом хранилище, но для нормальной работы нормальной программы все-таки рекомендую ограничить пользователя одним хранилищем.

После выбора сертификата из данного хранилища уже (заранее!) известно, что данный сертификат содержит привязку к ключевому контейнеру (иначе данный сертификат просто не будет отображаться в хранилище "My" и не будет доступен для выбора). Другой вопрос, что существование данного контейнера ключей и секретного ключа в нем должна быть проверена. Как это сделать уже рассказали.

Также после выбора сертификата известен криптопровайдер на котором можно выполнять операции подписи/шифрования (вообще-то не все сертификаты можно использовать одновременно для всех этих действий, но ограничимся простым примером). У данного криптопровайдера перебираем все его алгоритмы (ранее тоже пояснили как именно) и предлагаем их для выбора пользователю.

После все этих манипуляций получаем полный набор информации для осуществления необходимой операции.
С уважением,
Юрий Строжевский
Offline AndreyM  
#20 Оставлено : 27 февраля 2008 г. 14:48:23(UTC)
AndreyM

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

Группы: Участники
Зарегистрирован: 15.02.2008(UTC)
Сообщений: 11

Чтобы зашифровать данные не обязательно ведь, чтобы у сертификата была ссылка на контейнер с закрытым ключем. Или я не прав?
И кстати в хранилице MY можно установить сертификат у которого есть только открытый ключ. И отображаться он там будет. И даже наверное зашифровать что-нибудь им получится.

Я решил делать по такому алгоритму:
Сначала выбираем криптопровайдер, потом перечисляем его алгоритмы CryptGetProvParam(.., PP_ENUMALGS, ..) и, о да, как долго я искал как сделать, с помощью GET_ALG_CLASS(x) проверяем чтобы алгоритм был ALG_CLASS_DATA_ENCRYPT (EncryptAlgorithm.pszObjId ведь параметр указывает на алгоритм шифрования данных сессионным ключем). Потом показываем сертификаты CryptUIDlgSelectCertificate из хранилища MY но потом наверное придется из того, куда ставятся сертификаты от других пользователей, фильтруя из так, чтобы у сертификата pRecipientCert->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId присутствовал в списке поддерживаемых алгоритмов выбранного ранее криптопровайдера.

И уже даже почти получилось это все реализовать :)
RSS Лента  Atom Лента
Пользователи, просматривающие эту тему
Быстрый переход  
Вы не можете создавать новые темы в этом форуме.
Вы не можете отвечать в этом форуме.
Вы не можете удалять Ваши сообщения в этом форуме.
Вы не можете редактировать Ваши сообщения в этом форуме.
Вы не можете создавать опросы в этом форуме.
Вы не можете голосовать в этом форуме.