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

Уведомление

Icon
Error

5 Страницы123>»
Опции
К последнему сообщению К первому непрочитанному
Offline LONG11  
#1 Оставлено : 12 апреля 2020 г. 13:19:27(UTC)
LONG11

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

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

Сказал(а) «Спасибо»: 24 раз
Добрый день.
Можно ли обойтись без КриптоПро .NET для задачи получения сертификата из ключевого контейнера на etoken?

Дано:
1) на тестовой УЦ сформировал закрытый ключ на etoken
2) с помощью CSP 5.0 выпущенный сертификат также разместил в ключевой контейнере на etoken
3) С помощью C# и Crypto Api, ссылки на криптопровайдера - получаю имя контейнера etoken

Итак, я нахожусь на:

Код:
csp = new CspParameters();
csp.ProviderType = 80;
csp.KeyContainerName = AccessContList[i]; // содержит имя контейнера


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

Конечно, с КриптоПро .Net я могу использовать:
Код:
cspGost = new Gost3410_2012_256CryptoServiceProvider(csp);
selCertGOST = cspGost.ContainerCertificate;
//могу проверить алгоритм
selCertGOST.GetKeyAlgorithm() != "1.2.643.7.1.1.1.1" 
//могу проверить действительность
selCertGOST.Verify();


Но могу ли я это сделать без помощи КриптоПро .Net, а используя Crypto Api или же например каких либо иных средств?
Offline Андрей *  
#2 Оставлено : 12 апреля 2020 г. 14:46:25(UTC)
Андрей *

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

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

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

p/invoke - использовать неуправляемый код, MS CryptoAPI 2.0.
примеры работы с контейнерами - есть на форуме\в sdk к CSP
Техническую поддержку оказываем тут
Наша база знаний
thanks 1 пользователь поблагодарил Андрей * за этот пост.
LONG11 оставлено 12.04.2020(UTC)
Offline LONG11  
#3 Оставлено : 12 апреля 2020 г. 14:49:32(UTC)
LONG11

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

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

Сказал(а) «Спасибо»: 24 раз
Спасибо за подсказку, приступаю к изучению.
Offline Андрей *  
#4 Оставлено : 12 апреля 2020 г. 15:25:31(UTC)
Андрей *

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

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

Сказал «Спасибо»: 494 раз
Поблагодарили: 2034 раз в 1578 постах
Примерный прототип:
CSP_Name имя
CSP_Type тип

CryptAcquireContextA(hProv, nil, CSP_Name, CSP_Type, CRYPT_VERIFYCONTEXT
Перечислить контейнеры... (запомнить и прочее)
в цикле CryptGetProvParam(hProv, PP_ENUMCONTAINERS.... DataLen)
выделить память // GetMem(pbData, DataLen)
вызвать CryptGetProvParam(hProv, PP_ENUMCONTAINERS, pbData, DataLen, Flag)

pbData будет содержать имя контейнера


Подключиться к конкретному контейнеру CryptAcquireContext(hCSP...
CryptGetUserKey(hCSP, AT_KEYEXCHANGE, phUserKey)
получить информацию о сертификате:
CryptGetKeyParam(phUserKey, KP_CERTIFICATE ... pdwDataLen)
выделить память для pbCertificate - размер pdwDataLen
CryptGetKeyParam(phUserKey, KP_CERTIFICATE, pbCertificate, pdwDataLen, 0)
получить контекст сертификата:
pCertContext := CertCreateCertificateContext(X509_ASN_ENCODING, pbCertificate, pdwDataLen);

показать сертификат в стандартном окне ОС:
CryptUIDlgViewContext(CERT_STORE_CERTIFICATE_CONTEXT, pCertContext, 0, pwszTitle,
Техническую поддержку оказываем тут
Наша база знаний
thanks 2 пользователей поблагодарили Андрей * за этот пост.
LONG11 оставлено 12.04.2020(UTC), sniker оставлено 06.06.2023(UTC)
Offline Андрей *  
#5 Оставлено : 12 апреля 2020 г. 15:33:10(UTC)
Андрей *

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

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

Сказал «Спасибо»: 494 раз
Поблагодарили: 2034 раз в 1578 постах
поиск по ключевым словам\функциям:

пример:
https://www.cryptopro.ru...ts&m=96454#post96454
Техническую поддержку оказываем тут
Наша база знаний
thanks 1 пользователь поблагодарил Андрей * за этот пост.
LONG11 оставлено 12.04.2020(UTC)
Offline LONG11  
#6 Оставлено : 12 апреля 2020 г. 20:30:24(UTC)
LONG11

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

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

Сказал(а) «Спасибо»: 24 раз
Спасибо Вам огромное!!!

Объект X509Certificate2 получил. Валидность проверил.
То есть с токеном научился работать (в рамках моей задачи).

Теперь буду искать метод подписи файла PDF не Sharpei-ем, а также c помощью Win Crypto Api.
Работать с полями документа PDF при помощи itextSharp понял как.
Осталось только собственно метод подписания понять с помощью Win Crypto Api.

Offline LONG11  
#7 Оставлено : 12 апреля 2020 г. 22:17:41(UTC)
LONG11

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

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

Сказал(а) «Спасибо»: 24 раз
Еще разрешите вопрос, возможно для этого нужна новая тема, так как вопрос больше общие, но поскольку проверять буду действующим инструментарием, спрошу здесь:

Какие реквизиты проверять, чтобы удостоверится, что пользователь подписывает сертификатом Крипто-Про? Возможно формулировка и дилетантская.

Так как мне кажется, что
Код:
X509Certificate2.Verify
- вернет валидность проверки сертификата по цепочке. А как проверить, что сертификат однозначно выдан Крипто-Про?

Достаточно ли считать свойство
Код:
Issuer 
= сейчас на тестовом выдает:

Код:
"CN=\"Тестовый подчиненный УЦ ООО \"\"КРИПТО-ПРО\"\" ГОСТ 2012 (УЦ 2.0)\", O=\"ООО \"\"КРИПТО-ПРО\"\"\", STREET=ул. Сущёвский вал д. 18, L=Москва, S=77 Москва, C=RU, ИНН=007717107991, ОГРН=1037700085444, E=info@cryptopro.ru"





Offline Андрей *  
#8 Оставлено : 12 апреля 2020 г. 22:40:59(UTC)
Андрей *

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

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

Сказал «Спасибо»: 494 раз
Поблагодарили: 2034 раз в 1578 постах
Зависит от конечной цели...

Варианты:
а) анализ CN
б) анализ идентификатора ключа ЦС пользовательского сертификата, список брать из реестра аккредитованных УЦ - http://e-trust.gosuslugi...?ogrn=1037700085444&

p.s. - вариант а) - можно обойти, выпустить сертификат от "тестового" УЦ с нужным именем (или вообще сделать самоподписанный с нужным CN)

Техническую поддержку оказываем тут
Наша база знаний
thanks 1 пользователь поблагодарил Андрей * за этот пост.
LONG11 оставлено 12.04.2020(UTC)
Offline Андрей *  
#9 Оставлено : 12 апреля 2020 г. 22:44:40(UTC)
Андрей *

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

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

Сказал «Спасибо»: 494 раз
Поблагодарили: 2034 раз в 1578 постах
идентификатор ключа ЦС - это AuthorityKeyIdentifier
Техническую поддержку оказываем тут
Наша база знаний
thanks 1 пользователь поблагодарил Андрей * за этот пост.
LONG11 оставлено 12.04.2020(UTC)
Offline LONG11  
#10 Оставлено : 16 апреля 2020 г. 20:36:42(UTC)
LONG11

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

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

Сказал(а) «Спасибо»: 24 раз
Разрешите еще вопрос, собственно продолжение. Не особо я продвинулся в части подписания файла PDF присоединенной подписью.
По предыдущим шагам я не продвинулся далее чем:

Код:
CryptGetKeyParam(hPubKey, KP_CERTIFICATE, sb, ref pcbData, 0);
var pCertContext = CertCreateCertificateContext(X509_ASN_ENCODING, sb, (int)pcbData);
X509Certificate2 x509 = new X509Certificate2();
[b]x509[/b].Import(sb);
var isCapiValid = x509.Verify(); //проверка просто так


Далее я шел путем из примера SDK simple35 по подписанию PDF. И понимаю. что делаю что-то не так.

Код далее (он собственно из примера):

Код:
            PdfReader reader = null;
            FileStream fs = null;
            PdfStamper st = null;
            string destFNameTmp = "";
            string fPath = "";

            fPath = "F:\\Etalon.pdf";
            destFNameTmp = "F:\\Etalon-sign.pdf";

            reader = new PdfReader(fPath);
            fs = new FileStream(destFNameTmp, FileMode.Create, FileAccess.Write);
            st = PdfStamper.CreateSignature(reader, fs, '\0', null, true);
           
            AcroFields af = reader.AcroFields;
            List<string> signFieldNames = new List<string>();
            signFieldNames = af.GetSignatureNames();

            PdfSignatureAppearance sap = st.SignatureAppearance;

            sap.CertificationLevel = PdfSignatureAppearance.CERTIFIED_FORM_FILLING_AND_ANNOTATIONS;

            X509CertificateParser parser = new X509CertificateParser();
            Org.BouncyCastle.X509.X509Certificate[] chain =
                    new Org.BouncyCastle.X509.X509Certificate[] { parser.ReadCertificate(x509.RawData) };

            sap.Certificate = chain[0];
            sap.SignDate = DateTime.Now;
            sap.Reason = "Reason!";
            sap.Location = "Location!";

            // Выбираем подходящий тип фильтра
            PdfName filterName = new PdfName("CryptoPro PDF");
            // Создаем подпись
            PdfSignature dic = new PdfSignature(filterName, PdfName.ADBE_PKCS7_DETACHED);
            dic.Date = new PdfDate(DateTime.Now);
            dic.Name = "Sign-test";
            dic.Reason = "Reason!";
            dic.Location = "Location!";
            sap.CryptoDictionary = dic;
            int intCSize = 4000;
            Dictionary<PdfName, int> hashtable = new Dictionary<PdfName, int>();
            hashtable[PdfName.CONTENTS] = intCSize * 2 + 2;

            sap.PreClose(hashtable);
            Stream s = sap.GetRangeStream();

            MemoryStream ms = new MemoryStream();
            int read = 0;
            byte[] buff = new byte[8192];
            while ((read = s.Read(buff, 0, 8192)) > 0)
            {
                ms.Write(buff, 0, read);
            }
            ContentInfo contentInfo = new ContentInfo(ms.ToArray());
            SignedCms signedCms = new SignedCms(contentInfo, true);
            CmsSigner cmsSigner = new CmsSigner([b]x509[/b]); [b]//Кажется тут я делаю совершенно не верно, так как x509 не содержит ссылку на закрытый ключ на токене[/b]
            byte[] pk = null;

            try
            {
                // вываливаюсь на этой строке с ошибкой:
                // { "Ключ не существует.\r\n"}

                signedCms.ComputeSignature(cmsSigner, false); //если не ввести container password - исключение
                pk = signedCms.Encode();
            }
            catch (Exception Ex)
            {
            }

            byte[] outc = new byte[intCSize];
            PdfDictionary dic2 = new PdfDictionary();
            Array.Copy(pk, 0, outc, 0, pk.Length);

            dic2.Put(PdfName.CONTENTS, new PdfString(outc).SetHexWriting(true));
            sap.Close(dic2);
            fs.Close();
            st.Close();
            reader.Close();



Вываливаюсь на этой строке с ошибкой:
Код:
signedCms.ComputeSignature(cmsSigner, false); //если не ввести container password - исключение

с ошибкой: { "Ключ не существует.\r\n"}

Я понимаю, что кажется подменяю понятия использования Shappei, когда создается объект:
Код:
Gost3410_2012_256CryptoServiceProvider //и из него получается ссылка на 
certGOST = cspGost.ContainerCertificate;


Вместо этого я впихиваю свой объект:
Код:
[b]x509[/b].Import(sb);




Подскажите, пожалуйста, как исправить код? Хотя бы сценарий исправления.

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