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

Уведомление

Icon
Error

2 Страницы12>
Опции
К последнему сообщению К первому непрочитанному
Offline Infopol  
#1 Оставлено : 6 ноября 2023 г. 8:16:11(UTC)
Infopol

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

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

Сказал(а) «Спасибо»: 17 раз
Приветствую!Возникла такая проблема.При старте программы нужно определить наличие подключения ключа ЭЦП
Online Андрей *  
#2 Оставлено : 6 ноября 2023 г. 11:12:45(UTC)
Андрей *

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

Группы: Участники
Зарегистрирован: 26.07.2011(UTC)
Сообщений: 13,342
Мужчина
Российская Федерация

Сказал «Спасибо»: 550 раз
Поблагодарили: 2213 раз в 1727 постах
Здравствуйте.

1. Перечислить доступные контейнеры, перечислить сертификаты и связанные с ними контейнеры, сверить наличие.
или
2. Если известен сертификат, который требуется для работы в приложении - просто подписать случайную строчку - если не вставлен токен - будет запрос, а далее как повезёт: вставят и подпишется или будет отказ от пользователя (не стал подключать\забыл пароль).

Все примеры есть в SDK (с++) и здесь на форуме (и delphi).
Техническую поддержку оказываем тут
Наша база знаний
Online Андрей *  
#3 Оставлено : 6 ноября 2023 г. 11:13:59(UTC)
Андрей *

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

Группы: Участники
Зарегистрирован: 26.07.2011(UTC)
Сообщений: 13,342
Мужчина
Российская Федерация

Сказал «Спасибо»: 550 раз
Поблагодарили: 2213 раз в 1727 постах
Цитата:
Какой функцией в Delphi определить наличие подключенного ключа ЭЦП?

Что это даст, если токен вставлен не тот?
Техническую поддержку оказываем тут
Наша база знаний
Offline Infopol  
#4 Оставлено : 7 ноября 2023 г. 16:22:48(UTC)
Infopol

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

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

Сказал(а) «Спасибо»: 17 раз
Нужно проверить вставлен ли ключ и соответствует ИНН подписи ИНН клиента
Online Андрей *  
#5 Оставлено : 7 ноября 2023 г. 16:36:53(UTC)
Андрей *

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

Группы: Участники
Зарегистрирован: 26.07.2011(UTC)
Сообщений: 13,342
Мужчина
Российская Федерация

Сказал «Спасибо»: 550 раз
Поблагодарили: 2213 раз в 1727 постах
Автор: Infopol Перейти к цитате
Нужно проверить вставлен ли ключ и соответствует ИНН подписи ИНН клиента


В ключе нет ИНН.

ИНН есть в сертификате,
сертификат может быть в Личном хранилище или контейнере.

Итого получается:
получить список контейнеров, поиск сертификата в каждом контейнере и чтение информации.


А если сертификата не будет в контейнере?

И бонусом - а если клиент сделает тестовый сертификат с ИНН другого клиента - тоже получит доступ?
Техническую поддержку оказываем тут
Наша база знаний
Online Андрей *  
#6 Оставлено : 7 ноября 2023 г. 16:52:24(UTC)
Андрей *

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

Группы: Участники
Зарегистрирован: 26.07.2011(UTC)
Сообщений: 13,342
Мужчина
Российская Федерация

Сказал «Спасибо»: 550 раз
Поблагодарили: 2213 раз в 1727 постах
CryptAcquireContext к нужному криптопровайдеру (имя\тип) в режиме CRYPT_VERIFYCONTEXT

в цикле:
CryptGetProvParam (..PP_ENUMCONTAINERS...)
выделить память
CryptGetProvParam (..PP_ENUMCONTAINERS.. указатель на память = pbData)
добавить pbData в список контейнеров..


потом по контейнерам (или в цикле выше):

CryptAcquireContext(или использовать ранее полученный указатель)
CryptGetUserKey ( AT_KEYEXCHANGE + проверить, если будет ошибка на тип AT_SIGNATURE)



CryptGetKeyParam(phUserKey, KP_CERTIFICATE...
выделить память под сертификат
CryptGetKeyParam(phUserKey, KP_CERTIFICATE, указатель на память = pbCertificate)


pCertContext := CertCreateCertificateContext(X509_ASN_ENCODING, pbCertificate, ..)

из pCertContext получаем информацию по субъекту и нужные значения по OID-ам (ИНН\СНИЛС\ФИО\...)
Техническую поддержку оказываем тут
Наша база знаний
thanks 2 пользователей поблагодарили Андрей * за этот пост.
Infopol оставлено 09.11.2023(UTC), clipper оставлено 18.11.2023(UTC)
Offline two_oceans  
#7 Оставлено : 1 декабря 2023 г. 12:03:37(UTC)
two_oceans

Статус: Эксперт

Группы: Участники
Зарегистрирован: 05.03.2015(UTC)
Сообщений: 1,602
Российская Федерация
Откуда: Иркутская область

Сказал(а) «Спасибо»: 110 раз
Поблагодарили: 395 раз в 366 постах
Автор: Андрей * Перейти к цитате

CryptGetProvParam (..PP_ENUMCONTAINERS...)
потом по контейнерам (или в цикле выше):
CryptAcquireContext(или использовать ранее полученный указатель)
CryptGetUserKey ( AT_KEYEXCHANGE + проверить, если будет ошибка на тип AT_SIGNATURE)
CryptGetKeyParam(phUserKey, KP_CERTIFICATE...
выделить память под сертификат
CryptGetKeyParam(phUserKey, KP_CERTIFICATE, указатель на память = pbCertificate)
pCertContext := CertCreateCertificateContext(X509_ASN_ENCODING, pbCertificate, ..)
из pCertContext получаем информацию по субъекту и нужные значения по OID-ам (ИНН\СНИЛС\ФИО\...)
Добрый день. Ой-ей. На мой взгляд это не совсем соответствует поставленной задаче.

Суть в том, что есть ведь 2 подхода к сопоставлению контейнеров и сертификатов, отличающиеся тем что происходит вперед - перечисление контейнеров или перечисление сертификатов в хранилище. У обоих подходов свои плюсы и минусы. Описанный выше вариант оптимален только если перечислять контейнеры и вложенным циклом перечислять сертификаты. Поясню минусы такого подхода:
1) сертификат должен быть установлен в контейнер, если сертификата в контейнере нет, то ой (смотрите работу плагина госуслуг);
2) если пользователь вставил контейнер, то все перечисляем сначала, а ведь обращение к токенам занимает намного больше времени и иногда приводит к запросу паролей контейнера;
3) нет никакого встроенного кэширования в разрезе "этому контейнеру соответствует такой-то сертификат", только вычитка по одному;
4) а в контейнере чисто теоретически может быть даже 2 ключа те самые AT_KEYEXCHANGE и AT_SIGNATURE.
Плюсы:
1) сертификат не нужно устанавливать в "Личные";
2) сразу знаем что токен точно вставлен, но не знаем что на нем.
В то же время при перечислении сертификатов в хранилище минусы:
1) неизвестно заранее ли вставлен токен (но можно выясниить чуть позже);
2) сертификат надо установить в хранилище (обычно в Личные) иначе не увидится, желательно с привязкой к контейнеру, чтобы использовать все возможности. Не установлен, с неправильной привязкой или без привязки, то ой (смотрите работу плагина криптопро). Впрочем, служба смарт-карт каждый раз перепривязывает сертификаты с токена (в отличие от флешек, реестра) когда токен вставляется, так что достаточно включить службу и своевременно чистить старые контейнеры с токена.
Плюсы:
1) можем получить всю информацию по сертификату (ИНН и т.д.) сразу, не обращаясь к контейнеру и не запрашивая никаких пин-кодов;
2) из хранилища сертификатов помимо самого сертификата можно прочитать ту самую привязку на контейнер и вообще исключить шаг перечисления контейнеров и чтения данных сертификата из контейнера. Привязка содержит имя контейнера и те самые константы AT_KEYEXCHANGE или AT_SIGNATURE смотря уже какая нужна - их перебирать не требуется. Другими словами, при установке в хранилище эти данные запоминаются и доступны в любой момент до удаления сертификата из хранилища. Кроме того, со времен 3.6 R3 сертифицировано использование функции автоматического получения HPROV по привязке из хранилища сертификатов (но правда она выдаст запрос пользователю если токен не вставлен). Если же хотите запрос обойти, то придется получить и запомнить имена "нужных" контейнеров, а после перечисления всех сертификатов разок перечислить контейнеры (это быстрее чем их перечислять во вложенном цикле и быстрее чем вычитывать сертификат из каждого контейнера на токене);
3) в функцию перечисления сертификатов в хранилище встроен утилизатор ненужных контекстов сертификатов. передаете прошлый перечисленный, получаете следующий. Уменьшается вероятность, что забудете закрыть какой-то контекст сертификата и вызвать утечку памяти.

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

Когда я начинал знакомство с темой криптографии, меня тоже направили через контейнер узнавать сертификат, но немного поварившись в теме я понял, что перечисление сертификатов в хранилище намного более быстрый подход. Пользователь, честно говоря, переживет напоминание о том, что надо вставить токен, а вот медленное формирование списка доступных сертификатов очень раздражает. Уже при 15 сертификатах и контейнерах плагин Госуслуг может висеть полторы-две-три минуты. В то время как плагин Криптопро резво выдает перечень сертификатов на страничке тестирования.

По поводу поиска по ИНН, ну тоже есть нюансы:
1) вспомните, что ИНН организации немного раньше писали в тоже поле что ИНН физлица, где с нулями впереди, где без нулей;
2) соответственно новое поле ИНН организации есть не во всех сертификатах;
3) даже если есть, структурированный разбор субъекта на поля и сравнение данных занимает время. Да, небольшое. Однако помножить на число сертификатов и на число подписываемых документов - выйдет немало времени.
Как по мне быстрее получить бинарный вид сертификата из контекста и напрямую искать в нем ИНН. Нашелся - берем в работу (на подписание или на детальный разбор), не нашелся - детальный разбор тоже не найдет, "давай до свидания". Минус разве что в том, что бинарное значение может содержать нулевые байты и строковые функции поиска не подойдут, надо двоичные.

Ну и собственно для полноты - в хранилище есть встроенный индекс по идентификатору ключа и по отпечатку сертификата, так что искать по ним будет гораздо быстрее чем по ИНН. Как вариант, добавить регистрацию сертификата в Вашей программе и сопоставить ИНН с отпечатком, искать по отпечатку.
Online Андрей *  
#8 Оставлено : 1 декабря 2023 г. 13:41:27(UTC)
Андрей *

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

Группы: Участники
Зарегистрирован: 26.07.2011(UTC)
Сообщений: 13,342
Мужчина
Российская Федерация

Сказал «Спасибо»: 550 раз
Поблагодарили: 2213 раз в 1727 постах
Автор: two_oceans Перейти к цитате
Автор: Андрей * Перейти к цитате

CryptGetProvParam (..PP_ENUMCONTAINERS...)
потом по контейнерам (или в цикле выше):
CryptAcquireContext(или использовать ранее полученный указатель)
CryptGetUserKey ( AT_KEYEXCHANGE + проверить, если будет ошибка на тип AT_SIGNATURE)
CryptGetKeyParam(phUserKey, KP_CERTIFICATE...
выделить память под сертификат
CryptGetKeyParam(phUserKey, KP_CERTIFICATE, указатель на память = pbCertificate)
pCertContext := CertCreateCertificateContext(X509_ASN_ENCODING, pbCertificate, ..)
из pCertContext получаем информацию по субъекту и нужные значения по OID-ам (ИНН\СНИЛС\ФИО\...)
Добрый день. Ой-ей. На мой взгляд это не совсем соответствует поставленной задаче.


А как Вы поняли его задачу и мои ответы?

на тот момент моё понимание:
Ему не нужно знать, есть ли сертификат в хранилище.
Ему нужно знать, если ли сейчас токен, нужный ему.
Такая постановка задачи.
Если нет, тогда нет смысла дальше додумывать, автор поправит, если не забыл эту тему.

По ТЗ:
Это можно узнать получив оба списка, список контейнеров (и внутри искать по реквизитам в сертификате) и имя контейнера у сертификата (если начали от хранилища искать).


Насчёт резвости плагинов...
Со времен 13ххх версии плагина на тестовой вставлена работа с сертификатами в контейнерах
+ сравнение с ранее полученным списком, чтобы не дублировать вывод.

Соответственно, при наличии вставленного токена - такая же ситуация, пока он не "отморгает" (у меня минуту, две..),
показался быстро список сертификатов из Личного, а потом... "ждем".

За это время невнимательный пользователь даже может успеть позвонить или написать в ТП (не вижу сертификат).


Анализ самого сертификата занимает мало времени, у меня в тесте на слабом железе сбор всех данных: 1-2 мсек.
Т.е. на 1к тратится 1-2 с.

certs.png (100kb) загружен 7 раз(а).

Цитата:


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


либо здесь сканирование контейнеров для того, чтобы работать в авторежиме, без "вставьте токен",
когда есть токен - подписывать (но странно, правильнее поставить сертификат, либо это специально отключено и получаем такое ТЗ), также вопрос к паролю "открыт". Запоминает ли его приложение\скзи, либо это может быть активный токен...
Техническую поддержку оказываем тут
Наша база знаний
Online Андрей *  
#9 Оставлено : 1 декабря 2023 г. 13:51:09(UTC)
Андрей *

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

Группы: Участники
Зарегистрирован: 26.07.2011(UTC)
Сообщений: 13,342
Мужчина
Российская Федерация

Сказал «Спасибо»: 550 раз
Поблагодарили: 2213 раз в 1727 постах
/cades/demopage/async_code.js

Snimok ehkrana ot 2023-12-01 14-47-45.png (50kb) загружен 11 раз(а).
Техническую поддержку оказываем тут
Наша база знаний
Offline Санчир Момолдаев  
#10 Оставлено : 1 декабря 2023 г. 14:20:27(UTC)
Санчир Момолдаев

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

Группы: Модератор, Участники
Зарегистрирован: 03.12.2018(UTC)
Сообщений: 1,206
Российская Федерация

Сказал(а) «Спасибо»: 100 раз
Поблагодарили: 278 раз в 258 постах
Автор: Infopol Перейти к цитате
Приветствую!Возникла такая проблема.При старте программы нужно определить наличие подключения ключа ЭЦП


если речь про наличие съемных носителей (рутокен и пр)
Код:
HCRYPTPROV hCryptProv = 0;

	if (!CryptAcquireContext(
			&hCryptProv,
			NULL,
			NULL,
			PROV_GOST_2012_256,
			CRYPT_VERIFYCONTEXT))
	{
		cout << "Acquire context failed \n";
		return 1;
	}
...
DWORD dwFlags = CRYPT_FIRST | CRYPT_FQCN | PP_MEDIA_TYPE;
...
while (CryptGetProvParam(hCryptProv, PP_ENUMCONTAINERS, pbContainerName, &cbContainerName, dwFlags))
	{
		...
		dwFlags = CRYPT_NEXT;
	}

Отредактировано пользователем 1 декабря 2023 г. 14:27:28(UTC)  | Причина: Не указана

Техническую поддержку оказываем тут
Наша база знаний
thanks 1 пользователь поблагодарил Санчир Момолдаев за этот пост.
Андрей * оставлено 01.12.2023(UTC)
RSS Лента  Atom Лента
Пользователи, просматривающие эту тему
Guest
2 Страницы12>
Быстрый переход  
Вы не можете создавать новые темы в этом форуме.
Вы не можете отвечать в этом форуме.
Вы не можете удалять Ваши сообщения в этом форуме.
Вы не можете редактировать Ваши сообщения в этом форуме.
Вы не можете создавать опросы в этом форуме.
Вы не можете голосовать в этом форуме.