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

Уведомление

Icon
Error

5 Страницы<1234>»
Опции
К последнему сообщению К первому непрочитанному
Offline LONG11  
#11 Оставлено : 16 апреля 2020 г. 22:14:27(UTC)
LONG11

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

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

Сказал(а) «Спасибо»: 24 раз
Скорее всего моя ошибка в том. что изначально я спрашивал как получить список сертификатов с токена и Вы мне именно на это вопрос и ответили.

CryptGetKeyParam(hPubKey, KP_CERTIFICATE, sb, ref pcbData, 0);

Т.е. указывая KP_CERTIFICATE - "pbData - это адрес буфера, который получает сертификат X.509, который был закодирован с использованием" я получаю доступ на чтение для пользовательского сертификата в контейнере на токене, но не имею доступа к закрытому ключу.

Это так?
Подскажите, куда как двигаться в сторону подписи файла....

Дополню:
Код:
var b = x509.PrivateKey;

Результат:
b=null

Да, я что-то совсем не понимаю в матчасти. Пожалуйста, укажите на ошибки.

Отредактировано пользователем 16 апреля 2020 г. 23:13:01(UTC)  | Причина: Не указана

Offline Андрей *  
#12 Оставлено : 17 апреля 2020 г. 1:23:20(UTC)
Андрей *

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

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

Сказал «Спасибо»: 494 раз
Поблагодарили: 2035 раз в 1579 постах
Да, вопрос был про считывание сертификата.


Цитата:
>>
x509 .Import(sb)

CmsSigner cmsSigner = new CmsSigner( x509 ); //Кажется тут я делаю совершенно не верно, так как x509 не содержит ссылку на закрытый ключ на токене


Т.е. если установить сертификат с привязкой к токену в Личное и потом использовать в cmsSigner - то подписание PDF будет успешным...?

Техническую поддержку оказываем тут
Наша база знаний
Offline LONG11  
#13 Оставлено : 17 апреля 2020 г. 9:30:57(UTC)
LONG11

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

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

Сказал(а) «Спасибо»: 24 раз
Автор: Андрей * Перейти к цитате
Да, вопрос был про считывание сертификата.


Цитата:
>>
x509 .Import(sb)

CmsSigner cmsSigner = new CmsSigner( x509 ); //Кажется тут я делаю совершенно не верно, так как x509 не содержит ссылку на закрытый ключ на токене


Т.е. если установить сертификат с привязкой к токену в Личное и потом использовать в cmsSigner - то подписание PDF будет успешным...?



Да, все верно. Сейчас проверил, если установить в личное, то работает. Прям сразу же свойство:
var b = x509.PrivateKey;
b=true

Но как можно обойтись без экспорта в личное? С каким параметром можно получать сертификат из Токена, чтобы он также "видел" закрытый ключ?

Добавлено:

Возможно нужно смотреть в сторону:
https://cpdn.cryptopro.ru/content/capilite40/html/group___key_func_1g626620ef5b49a785c8ddb9e64357a794.html

Но пока не понимаю порядок действий...

Отредактировано пользователем 17 апреля 2020 г. 9:52:15(UTC)  | Причина: Не указана

Offline Андрей *  
#14 Оставлено : 17 апреля 2020 г. 11:23:35(UTC)
Андрей *

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

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

Сказал «Спасибо»: 494 раз
Поблагодарили: 2035 раз в 1579 постах
CmsSigner - это .NET
CryptAcquireCertificatePrivateKey - это p\invoke.

Логично, что нужно одно что-то использовать, а не сращивать.

см. C# + CryptSignMessage

Техническую поддержку оказываем тут
Наша база знаний
thanks 1 пользователь поблагодарил Андрей * за этот пост.
LONG11 оставлено 17.04.2020(UTC)
Offline LONG11  
#15 Оставлено : 17 апреля 2020 г. 13:08:04(UTC)
LONG11

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

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

Сказал(а) «Спасибо»: 24 раз
Автор: Андрей * Перейти к цитате
CmsSigner - это .NET
CryptAcquireCertificatePrivateKey - это p\invoke.

Логично, что нужно одно что-то использовать, а не сращивать.

см. C# + CryptSignMessage



Я думаю, что уже давно понятно :), что решаю нетипичную для меня задачу и не ладах с C# и p\invoke. Судьба заставила написать крохотную DLL для подписания из нетиповой 1С, причем версии 1С 77. От того и вопросы мои нелогичны.
Позвольте сформулировать задачу (я частично ее уже писал):

1. Есть КриптоПро CSP.
2. На токене записан ключ и сертификат. В хранилище сертификаты устанавливать не планируется.
3. Подписать PDF по ГОСТ (видимая подпись как обязательное условие).
4. Крипто Про .NET есть и работает. Но есть желание (но нет знаний :)) уйти от него. Так как собственно используется из всего Крипто .NET лишь функция подписания.

С Вашей помощью да, научился опрашивать Токен на контейнеры и добираться до сертификата. Функция CryptSignMessage - сложная для меня, так как там передаются структуры и я в этом сяду в лужу.
Прельщало, что при установке сертификата из контейнера в хранилище MY в сертификат добавляется связь с приватным ключом. И далее работали методы .NET (CmsSigner), что не может не радовать.

И вот задача почти решена (да она по сути своей мизерна, но нам достаточна), однако в полученном по p\invoke сертификате нет связи с приватным ключом.

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

За назойливость приношу извинения.



Offline two_oceans  
#16 Оставлено : 19 апреля 2020 г. 11:02:26(UTC)
two_oceans

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

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

Сказал(а) «Спасибо»: 110 раз
Поблагодарили: 393 раз в 366 постах
Выше же вроде все основное описано
https://www.cryptopro.ru...&m=114343#post114343

Поясняю, в сообщении выше описан цикл получения данных перечислением имен контейнеров ContainerName -> hProv -> hPubKey -> CertData -> pCertContext. Ссылка на контейнер теряется когда получаете CertData (это только данные сертификата, но не какой-то объект), так как ссылка на контейнер является не частью сертификата, а свойством либо ключа/хэша (то есть напрямую полученные из hProv объекты хранят дескриптор hProv внутри) либо позиции хранящей сертификат в хранилище сертификатов (тут хранится тип провайдера и имя контейнера, hProv получается при необходимости).

Далее Вы либо можете:
1) в вновь созданный из CertData контекст сертификата сохранить ссылку на контейнер (так как Вы все равно получили данные сертификата из контейнера, то у Вас ссылка по сути уже есть, но надо ее сохранить в pCertContext);
2) поискать в хранилище сертификатов этот же сертификат с проставленной ссылкой на контейнер (это для случаев когда получили сертификат не из контейнера или вообще получили только отпечаток сертификата);
3) использовать hProv напрямую в низкоуровневых функциях поднисания. То есть каким-то своим способом сохраните соответствие сертификата и имени контейнера (с описателем нужен ключ обмена или ключ подписи из контейнера).
Судя по описанию задачи установка в хранилище сертификатов не предусмотрена; третий вариант наверно будет слишком сложен (хотя может и наоборот, как раз более сподручен для подписи PDF, не занимался подписыванием PDF, не знаю точно), тогда Вам остается вариант 1 и далее предложенная функция CryptSignMessage (структура там конечно большая, но есть куча примеров как ее заполнять на разных языках и средах программирования).

Отредактировано пользователем 19 апреля 2020 г. 11:28:59(UTC)  | Причина: Не указана

thanks 1 пользователь поблагодарил two_oceans за этот пост.
LONG11 оставлено 19.04.2020(UTC)
Offline Андрей *  
#17 Оставлено : 19 апреля 2020 г. 11:12:29(UTC)
Андрей *

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

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

Сказал «Спасибо»: 494 раз
Поблагодарили: 2035 раз в 1579 постах
Автор: two_oceans Перейти к цитате
Выше же вроде все описано
https://www.cryptopro.ru...&m=114343#post114343

Поясняю, в сообщении выше описан цикл получения данных ContainerName -> hProv -> hPubKey -> pCertContext


Так это другая ветка проблемы, её решили.
А результат не совместим с cmsSigner - в этом проблема.
Техническую поддержку оказываем тут
Наша база знаний
Offline Андрей *  
#18 Оставлено : 19 апреля 2020 г. 11:13:40(UTC)
Андрей *

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

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

Сказал «Спасибо»: 494 раз
Поблагодарили: 2035 раз в 1579 постах
Автор: LONG11 Перейти к цитате
Автор: Андрей * Перейти к цитате
CmsSigner - это .NET
CryptAcquireCertificatePrivateKey - это p\invoke.

Логично, что нужно одно что-то использовать, а не сращивать.

см. C# + CryptSignMessage



С Вашей помощью да, научился опрашивать Токен на контейнеры и добираться до сертификата. Функция CryptSignMessage - сложная для меня, так как там передаются структуры и я в этом сяду в лужу.




Чем сложная? если можно поиском найти готовый код вызова из C#
Техническую поддержку оказываем тут
Наша база знаний
Offline two_oceans  
#19 Оставлено : 19 апреля 2020 г. 11:32:12(UTC)
two_oceans

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

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

Сказал(а) «Спасибо»: 110 раз
Поблагодарили: 393 раз в 366 постах

Отредактировано пользователем 19 апреля 2020 г. 11:39:24(UTC)  | Причина: Не указана

Offline LONG11  
#20 Оставлено : 19 апреля 2020 г. 13:12:09(UTC)
LONG11

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

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

Сказал(а) «Спасибо»: 24 раз
Всем спасибо за отклики.
Лирика (больше к этому возвращаться не буду): так уж вышло, что с этой задачкой решил разобраться сам (не владея C#, ничего не ведая вообще о криптографии). Обсуждать почему так, наверное нет смысла, так уж вышло (правильно это или нет - тоже вопрос спорный - уж как есть). Соответственно вводная такая: решает задачу профан, на сильно узком специализированном форуме, где люди в теме и как программировать и что такое криптография, отсюда и сухие ответы и "нет рассусоливаний и вообще учится надо было в школе". Посему лишний раз не знаешь как сформулировать вопрос: ибо тут и синтаксис языка, тут и маршализация, тут абсолютное незнание предметной области и все это наслоение приводит к тому, что вопрос получится дурацким, на который ответа и не будет.

Поставленная задача благополучно решается с использованием КриптоПро .NET (скачал с сайт. проверил - работает). Просто весь функционал, заключается лишь в одном методе подписания только одного типа файлов (для нашей задачи). В общем решил попробовать обойтись без него.

Есть понимание того, что собственные усилия должны быть, и негоже сидеть и просить на форуме, я написал строчку "А", скорее говорите мне сточку "Б". Стараюсь, но да, незнание предметной области и средства разработки - это сильно ужасно)). Я все понимаю, спасибо всем, кто помогает.

Лирике конец.

Итак,

Автор: two_oceans Перейти к цитате

Далее Вы либо можете:
1) в вновь созданный из CertData контекст сертификата сохранить ссылку на контейнер (так как Вы все равно получили данные сертификата из контейнера, то у Вас ссылка по сути уже есть, но надо ее сохранить в pCertContext);

Вот этого бы и хотелось. Не понимаю как сделать. Ведь Крипто-Про .Net как-то это внутри себя делает, например:
Код:
CspParameters csp = null;
csp = new CspParameters();
csp.ProviderType = 80;
csp.KeyContainerName = "тут имя контейнера";
cspGost = new Gost3410_2012_256CryptoServiceProvider(csp);

И после этого, о чудо:
certGOST = cspGost.ContainerCertificate;
И тут тебе и ссылка на сертификат и его атрибуты (чтобы сверить с имеющимися подписями в файле: а не подписан ли этот PDF уже этим сертификатом - это для логики программы).
И ссылка на закрытый ключ, тоже доступна:
Код:
certGOST.PrivateKe 

И далее все подписывается .NET
Код:
CmsSigner cmsSigner = new CmsSigner(x509);
signedCms.ComputeSignature(cmsSigner, false); 

Именно поэтому и хотелось чтобы:
Код:
var pCertContext = CertCreateCertificateContext(X509_ASN_ENCODING, sb, (int)pcbData);
X509Certificate2 x509 = new X509Certificate2();
x509.Import(sb);

Каким-то образом содержал ссылку на контейнер закрытого ключа. Ведь Крипто-Про .Net как то ее получает. (Но на то видать он и отдельный удобный для разработчиков продукт).
И для меня бы p/invoke кончалось получением сертификата с токена (без необходимости помещения его в хранилище Личное). А дальше .Net.

Автор: two_oceans Перейти к цитате

2) поискать в хранилище сертификатов этот же сертификат с проставленной ссылкой на контейнер (это для случаев когда получили сертификат не из контейнера или вообще получили только отпечаток сертификата);

Покопавшись, я написал как сделать это программно, а именно крайне кривое решение (для моей задачи), программно экспортировать сертификат в Личное, с установкой на него ссылки на закрытый ключ:
Код:
CryptoApi.CRYPT_KEY_PROV_INFO cryptKeyProvInfo =
new CryptoApi.CRYPT_KEY_PROV_INFO();
cryptKeyProvInfo.pwszProvName = name;
cryptKeyProvInfo.pwszContainerName = container +'\0';
cryptKeyProvInfo.dwProvType = 80;
cryptKeyProvInfo.dwFlags = 1; // CERT_SET_KEY_CONTEXT_PROP_ID | CERT_SET_KEY_PROV_HANDLE_PROP_ID
cryptKeyProvInfo.cProvParam = 0;
cryptKeyProvInfo.rgProvParam = IntPtr.Zero;
cryptKeyProvInfo.dwKeySpec = 2 /* AT_SIGNATURE */;
pvData = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(CryptoApi.CRYPT_KEY_PROV_INFO)));
Marshal.StructureToPtr(cryptKeyProvInfo, pvData, false);
if (CryptoApi.CertSetCertificateContextProperty(certificate.Handle, 2 /* CERT_KEY_PROV_INFO_PROP_ID */, 0, pvData)) //
{
X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadWrite);
store.Add(certificate);
store.Close();
}

Затем искать этот сертификат в хранилище и найдя его (он содержит ссылку на закрытый ключ) спокойно использовать .Net. А потом подписав удалять его из Личного чтоль ...(так как по логике не хотим, чтобы он там хранился). Криво. Очень.
Я действительно (облазив форум и интернет) не смог понять, для контекста сертификата, который получен:
Код:
int certSize = 0;
if (!CryptoApi.CryptGetKeyParam(keyHandle, KP_CERTIFICATE, null, ref certSize, 0))
var certResult = new byte[certSize];
if (!CryptoApi.CryptGetKeyParam(keyHandle, KP_CERTIFICATE, certResult, ref certSize, 0))
var pCertContext = CryptoApi.CertCreateCertificateContext(X509_ASN_ENCODING, certResult, certSize);

Нельзя прописать ссылку на закрытый ключ, хотя этот сертификат же лежит рядом с закрытым ключем в контейнере на токене, и дальше им пользоваться с использованием CmsSigner, а вот если ты его экспортируешь в Личное, потом достанешь из Личного - то пожалуйста - пользуйся....Вот совсем не понимаю. Это бы решило мою задачу и все ). Но остается некое чувство (от недопонимания предметной области, хоть и курю интернет), что я чего-то не знаю, и можно установить ссылку и не использовать дальше p/invoke с его сложной для меня CryptSignMessage.

Автор: two_oceans Перейти к цитате

3) использовать hProv напрямую в низкоуровневых функциях подписания. То есть каким-то своим способом сохраните соответствие сертификата и имени контейнера (с описателем нужен ключ обмена или ключ подписи из контейнера).

Вот совсем растерялся и скажу честно не понял совсем.
Автор: two_oceans Перейти к цитате

Судя по описанию задачи установка в хранилище сертификатов не предусмотрена;

Да.
Автор: two_oceans Перейти к цитате

третий вариант наверно будет слишком сложен

Да.
Автор: two_oceans Перейти к цитате

тогда Вам остается вариант 1 и далее предложенная функция CryptSignMessage (структура там конечно большая, но есть куча примеров как ее заполнять на разных языках и средах программирования).

Видимо да. Примеры нашел. Даже из них пока многое непонятно, так как не подписывает пока. Следующим постом спрошу про параметры этого метода, напишу, что не понимаю в нем...

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