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

Уведомление

Icon
Error

Опции
К последнему сообщению К первому непрочитанному
Offline rmussalimov  
#1 Оставлено : 21 октября 2019 г. 15:54:22(UTC)
rmussalimov

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

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

Сказал(а) «Спасибо»: 4 раз
Добрый день!

Реализовал создание открепленной PKCS#7 подписи при помощи КриптоПро JCP

Однако, есть проблема:

В используемом методе (из jarника samples) агрументом является объект X509Certficiate (т.е. подписанта). Соответственно, в подпись включается только он.

Используемый метод:

Цитата:
/**
* Функция формирования простой отсоединенной подписи формата PKCS#7
* по хешу сообщения.
* Пример подписи взят из {@link CMS_samples.CMS#CMSSign(byte[],
* PrivateKey, Certificate, boolean)}.
*
* @param data Данные для подписи.
* @param privateKey Закрытый ключ для создания ЭЦП.
* @param certificate Сертификат подписи.
* @return ЭЦП.
* @throws Exception
*/
public static byte[] createPKCS7(byte[] data, PrivateKey privateKey,
X509Certificate certificate) throws Exception
{

// Получаем бинарную подпись длиной 64 байта.

final Signature signature = Signature.getInstance(AlgorithmUtils.getSignatureInstanceForJCP(certificate)); //hardcoded JCP.GOST_DHEL_SIGN_NAME
signature.initSign(privateKey);
signature.update(data);

final byte[] sign = signature.sign();

// Формируем контекст подписи формата PKCS7.

final ContentInfo all = new ContentInfo();
all.contentType = new Asn1ObjectIdentifier(
new OID(CMStools.STR_CMS_OID_SIGNED).value);

final SignedData cms = new SignedData();
all.content = cms;
cms.version = new CMSVersion(1);

// Идентификатор алгоритма хеширования.

String [] digestAndSignatureAlgorithms = AlgorithmUtils.getDigestSignatureAlgorithmOIDs(certificate);

cms.digestAlgorithms = new DigestAlgorithmIdentifiers(1);
final DigestAlgorithmIdentifier a = new DigestAlgorithmIdentifier(
new OID(digestAndSignatureAlgorithms[0]).value); //hardcoded CMStools.DIGEST_OID
a.parameters = new Asn1Null();
cms.digestAlgorithms.elements[0] = a;

// Т.к. подпись отсоединенная, то содержимое отсутствует.

cms.encapContentInfo = new EncapsulatedContentInfo(
new Asn1ObjectIdentifier(new OID(CMStools.STR_CMS_OID_DATA).value), null);

// Добавляем сертификат подписи.

cms.certificates = new CertificateSet(1);
final ru.CryptoPro.JCP.ASN.PKIX1Explicit88.Certificate asnCertificate =
new ru.CryptoPro.JCP.ASN.PKIX1Explicit88.Certificate();

final Asn1BerDecodeBuffer decodeBuffer =
new Asn1BerDecodeBuffer(certificate.getEncoded());
asnCertificate.decode(decodeBuffer);

cms.certificates.elements = new CertificateChoices[1];
cms.certificates.elements[0] = new CertificateChoices();
cms.certificates.elements[0].set_certificate(asnCertificate);

// Добавялем информацию о подписанте.

cms.signerInfos = new SignerInfos(1);
cms.signerInfos.elements[0] = new SignerInfo();
cms.signerInfos.elements[0].version = new CMSVersion(1);
cms.signerInfos.elements[0].sid = new SignerIdentifier();

final byte[] encodedName = certificate.getIssuerX500Principal().getEncoded();
final Asn1BerDecodeBuffer nameBuf = new Asn1BerDecodeBuffer(encodedName);
final Name name = new Name();
name.decode(nameBuf);

final CertificateSerialNumber num = new CertificateSerialNumber(
certificate.getSerialNumber());

cms.signerInfos.elements[0].sid.set_issuerAndSerialNumber(
new IssuerAndSerialNumber(name, num));
cms.signerInfos.elements[0].digestAlgorithm =
new DigestAlgorithmIdentifier(new OID(digestAndSignatureAlgorithms[0]).value); // hardcoded CMStools.DIGEST_OID
cms.signerInfos.elements[0].digestAlgorithm.parameters = new Asn1Null();
cms.signerInfos.elements[0].signatureAlgorithm =
new SignatureAlgorithmIdentifier(new OID(digestAndSignatureAlgorithms[1]).value); //hardcoded CMStools.SIGN_OID
cms.signerInfos.elements[0].signatureAlgorithm.parameters = new Asn1Null();
cms.signerInfos.elements[0].signature = new SignatureValue(sign);

// Получаем закодированную подпись.

final Asn1BerEncodeBuffer asnBuf = new Asn1BerEncodeBuffer();
all.encode(asnBuf, true);

return asnBuf.getMsgCopy();
}


В связи с этим у меня есть вопросы:

Как включить всю цепочку в подпись?
Откуда ее можно взять, если в контейнере у данного сертификата ее нет?
Откуда цепочка вообще берется?

Заранее спасибо.
Offline two_oceans  
#2 Оставлено : 22 октября 2019 г. 10:49:05(UTC)
two_oceans

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

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

Сказал(а) «Спасибо»: 110 раз
Поблагодарили: 393 раз в 366 постах
Автор: rmussalimov Перейти к цитате
Как включить всю цепочку в подпись?
Откуда ее можно взять, если в контейнере у данного сертификата ее нет?
Добрый день. Полагаю цепочку надо добавлять в cms.certificates.elements.
Как получить исчерпывающая инструкция буквально на странице 2 данного раздела форума https://www.cryptopro.ru...aspx?g=posts&t=16695
Еще почти тоже: https://www.cryptopro.ru...&m=107822#post107822
Автор: rmussalimov Перейти к цитате
Откуда цепочка вообще берется?
Вручную для построения цепочки можно зайти на e-trust.gosuslugi.ru и поискать сертификат УЦ выдавшего Ваш сертификат, алгоритм такой:
1. открываете сертификат (в начале свой, если перешли с шага 4, то скачанный сертификат УЦ) смотрите поле издатель - из него интересует огрн издателя, смотрите поле идентификатор ключа ЦС (тут интересуют только шестнадцатеричные цифры).
2. Если это не Минкомсвязь/головной удостоверяющий центр на сайте e-trust.gosuslugi.ru в меню переходите в аккредитованные УЦ, вводите огрн в поле фильтра, нажимаете найти, найдется один пункт, надо нажать лупу слева от названия УЦ. Если Минкомсвязь/головной удостоверяющий центр, то нужно на сайте в меню выбрать головной УЦ.
3. на странице УЦ находите соотвествующий сертификат по идентификатору ключа, скачиваете.
4. открываете сертификат УЦ, если это не Минкомсвязь/головной удостоверяющий центр - переходите к шагу 1, если Минкомсвязь/головной удостоверяющий центр - убеждаетесь что идентификатор ключа субъекта равен идентификатору ключа ЦС. Если равен, то это корневой сертификат и конец алгоритма, если не равен - переходите к шагу 1.

Программно все практически так же, но берется адрес из расширения сертификата сведения о ЦС - в котором указаны прямые адреса где лежит сертификат УЦ (не e-trust.gosuslugi.ru, а на сайте УЦ). Адрес может быть недоступен или отключено докачивание сертификатов цепочки или отключен Интернет - тогда цепочка не построится автоматически.

Отредактировано пользователем 22 октября 2019 г. 10:54:33(UTC)  | Причина: Не указана

Offline rmussalimov  
#3 Оставлено : 22 октября 2019 г. 12:36:02(UTC)
rmussalimov

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

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

Сказал(а) «Спасибо»: 4 раз
Автор: two_oceans Перейти к цитате
Автор: rmussalimov Перейти к цитате
Как включить всю цепочку в подпись?
Откуда ее можно взять, если в контейнере у данного сертификата ее нет?
Добрый день. Полагаю цепочку надо добавлять в cms.certificates.elements.
Как получить исчерпывающая инструкция буквально на странице 2 данного раздела форума https://www.cryptopro.ru...aspx?g=posts&t=16695
Еще почти тоже: https://www.cryptopro.ru...&m=107822#post107822
Автор: rmussalimov Перейти к цитате
Откуда цепочка вообще берется?
Вручную для построения цепочки можно зайти на e-trust.gosuslugi.ru и поискать сертификат УЦ выдавшего Ваш сертификат, алгоритм такой:
1. открываете сертификат (в начале свой, если перешли с шага 4, то скачанный сертификат УЦ) смотрите поле издатель - из него интересует огрн издателя, смотрите поле идентификатор ключа ЦС (тут интересуют только шестнадцатеричные цифры).
2. Если это не Минкомсвязь/головной удостоверяющий центр на сайте e-trust.gosuslugi.ru в меню переходите в аккредитованные УЦ, вводите огрн в поле фильтра, нажимаете найти, найдется один пункт, надо нажать лупу слева от названия УЦ. Если Минкомсвязь/головной удостоверяющий центр, то нужно на сайте в меню выбрать головной УЦ.
3. на странице УЦ находите соотвествующий сертификат по идентификатору ключа, скачиваете.
4. открываете сертификат УЦ, если это не Минкомсвязь/головной удостоверяющий центр - переходите к шагу 1, если Минкомсвязь/головной удостоверяющий центр - убеждаетесь что идентификатор ключа субъекта равен идентификатору ключа ЦС. Если равен, то это корневой сертификат и конец алгоритма, если не равен - переходите к шагу 1.

Программно все практически так же, но берется адрес из расширения сертификата сведения о ЦС - в котором указаны прямые адреса где лежит сертификат УЦ (не e-trust.gosuslugi.ru, а на сайте УЦ). Адрес может быть недоступен или отключено докачивание сертификатов цепочки или отключен Интернет - тогда цепочка не построится автоматически.


Спасибо за ответ.

Допустим, все сертификаты были скачаны, как определяется, что X сертификат выдан сертификат Y, который выдал сертификат Z (конечный)?

После этого в хранилище криптопро csp сертификаты будут связаны цепочкой? Т.е я смогу вызвать keyStore.getCertificateChain(String alias), и это вернет мне всю цепочку?

Далее будет ли возможно просто добавить в цикле cms.certificates полученную цепочку?
Offline Евгений Афанасьев  
#4 Оставлено : 22 октября 2019 г. 13:15:09(UTC)
Евгений Афанасьев

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

Группы: Участники
Зарегистрирован: 06.12.2008(UTC)
Сообщений: 3,910
Российская Федерация
Откуда: Крипто-Про

Сказал(а) «Спасибо»: 20 раз
Поблагодарили: 685 раз в 646 постах
Здравствуйте.
В samples-sources.jar в дистрибутиве в пакете userSamples есть примеры построения (и проверки) цепочки сертификатов CRLValidateCert (по CRL) и OCSPValidateCert (по OCSP или CRL) от target-сертификата (EE) до корневого, который должен быть в списке TrustAnchor. Дополнительные сертификаты (промежуточные) могут быть добавлены в addCertStore. CRLValidateCert с помощью enableAIAcaIssuers может догрузить промежуточные сертификаты из сети, если ссылки на них есть в сертификатов.
Offline two_oceans  
#5 Оставлено : 23 октября 2019 г. 6:18:04(UTC)
two_oceans

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

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

Сказал(а) «Спасибо»: 110 раз
Поблагодарили: 393 раз в 366 постах
Автор: rmussalimov Перейти к цитате
Допустим, все сертификаты были скачаны... После этого в хранилище криптопро csp сертификаты будут связаны цепочкой?
Добрый день. Отвечу в общем, без конкретики для Джавы. Если просто скачать, то эффекта никакого, нужно установить в хранилище корневых/промежуточных сертификатов. Информация о цепочке не сохраняется в хранилище и строится каждый раз, но приложение может на некоторое время "закэшировать" цепочку и статус сертификатов. Делает ли кэширование Джава точно сказать не могу, скорее нет (то есть проверка проводится каждый раз снова). Для Джавы корневой должен быть в списке TrustAnchor.
Автор: rmussalimov Перейти к цитате
как определяется, что X сертификат выдан сертификат Y, который выдал сертификат Z (конечный)?
Это наверно один из самых нестабильных вопросов отечественной криптографии. Самый надежный способ определять цепочку - по идентификатору ключа, как в сообщении выше. Для аккредитованных отечественных УЦ идентификатор ключа всегда присутствует. Однако, зарубежные стандарты указывают идентификатор ключа как необязательное расширение сертификата (во многих зарубежных сертификатах оно отсутствует), то есть механизмы встроенные в ОС (скажу за Windows) не полагаются на идентификатор ключа и не особенно гибко ищут по полям Субъект - Издатель, которые обязательные (предпочтение отдается элементу CN (если есть - в большинстве случаев есть) потом E (если есть E и нет CN) и так далее).
Offline rmussalimov  
#6 Оставлено : 23 октября 2019 г. 11:35:51(UTC)
rmussalimov

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

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

Сказал(а) «Спасибо»: 4 раз
Автор: Евгений Афанасьев Перейти к цитате
Здравствуйте.
В samples-sources.jar в дистрибутиве в пакете userSamples есть примеры построения (и проверки) цепочки сертификатов CRLValidateCert (по CRL) и OCSPValidateCert (по OCSP или CRL) от target-сертификата (EE) до корневого, который должен быть в списке TrustAnchor. Дополнительные сертификаты (промежуточные) могут быть добавлены в addCertStore. CRLValidateCert с помощью enableAIAcaIssuers может догрузить промежуточные сертификаты из сети, если ссылки на них есть в сертификатов.


Хорошо, можете тогда подсказать, пожалуйста, как будет выглядеть метод, который вместо X509Certificate будет принимать Certificate [] (массив сертификатов).

Сейчас в подпись сертификаты добавляются так.

Цитата:
// Добавляем сертификат подписи.

cms.certificates = new CertificateSet(1);
final ru.CryptoPro.JCP.ASN.PKIX1Explicit88.Certificate asnCertificate =
new ru.CryptoPro.JCP.ASN.PKIX1Explicit88.Certificate();

final Asn1BerDecodeBuffer decodeBuffer =
new Asn1BerDecodeBuffer(certificate.getEncoded());
asnCertificate.decode(decodeBuffer);

cms.certificates.elements = new CertificateChoices[1];
cms.certificates.elements[0] = new CertificateChoices();
cms.certificates.elements[0].set_certificate(asnCertificate);


Насколько понимаю, должен быть цикл.

Думаю, метод должен выглядеть так (массив сертификатов allCerts). 0-ой серт, это серт подписанта.

Цитата:
// Добавляем сертификатЫ подписи.

cms.certificates = new CertificateSet(allCerts.length);
cms.certificates.elements = new CertificateChoices[allCerts.length];

for(int i = 0; i < allCerts.length; i++)
{
final ru.CryptoPro.JCP.ASN.PKIX1Explicit88.Certificate asnCertificate =
new ru.CryptoPro.JCP.ASN.PKIX1Explicit88.Certificate();

final Asn1BerDecodeBuffer decodeBuffer =
new Asn1BerDecodeBuffer(allCerts[i].getEncoded());
asnCertificate.decode(decodeBuffer);

cms.certificates.elements[i] = new CertificateChoices();
cms.certificates.elements[i].set_certificate(asnCertificate);
}



Offline rmussalimov  
#7 Оставлено : 23 октября 2019 г. 11:36:41(UTC)
rmussalimov

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

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

Сказал(а) «Спасибо»: 4 раз
Автор: Евгений Афанасьев Перейти к цитате
Здравствуйте.
В samples-sources.jar в дистрибутиве в пакете userSamples есть примеры построения (и проверки) цепочки сертификатов CRLValidateCert (по CRL) и OCSPValidateCert (по OCSP или CRL) от target-сертификата (EE) до корневого, который должен быть в списке TrustAnchor. Дополнительные сертификаты (промежуточные) могут быть добавлены в addCertStore. CRLValidateCert с помощью enableAIAcaIssuers может догрузить промежуточные сертификаты из сети, если ссылки на них есть в сертификатов.


Как конкретно называется метод, который строит цепочку?
Offline Евгений Афанасьев  
#8 Оставлено : 23 октября 2019 г. 11:40:19(UTC)
Евгений Афанасьев

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

Группы: Участники
Зарегистрирован: 06.12.2008(UTC)
Сообщений: 3,910
Российская Федерация
Откуда: Крипто-Про

Сказал(а) «Спасибо»: 20 раз
Поблагодарили: 685 раз в 646 постах
Метод build класса CertPathBuilder, алгоритм и провайдер - "CPPKIX" и "RevCheck":

PKIXCertPathBuilderResult res = (PKIXCertPathBuilderResult) CertPathBuilder.getInstance("CPPKIX", "RevCheck").build(cpp);
cpp - параметры класса PKIXBuilderParameters, куда можно передать: сертификат, для которого строится цепочка, дополнительные хранилища для поиска сертификатов при построении, дату, список доверенных корневых (TrustAnchor) и т.д.
Offline rmussalimov  
#9 Оставлено : 23 октября 2019 г. 11:49:07(UTC)
rmussalimov

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

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

Сказал(а) «Спасибо»: 4 раз
Автор: Евгений Афанасьев Перейти к цитате
Метод build класса CertPathBuilder, алгоритм и провайдер - "CPPKIX" и "RevCheck":

PKIXCertPathBuilderResult res = (PKIXCertPathBuilderResult) CertPathBuilder.getInstance("CPPKIX", "RevCheck").build(cpp);
cpp - параметры класса PKIXBuilderParameters, куда можно передать: сертификат, для которого строится цепочка, дополнительные хранилища для поиска сертификатов при построении, дату, список доверенных корневых (TrustAnchor) и т.д.


Спасибо большое. Последний вопрос - данным методом цепочка строится локально? В нашем сертификате есть информация о промежуточном, только по URL он недоступен.
Offline Евгений Афанасьев  
#10 Оставлено : 23 октября 2019 г. 13:09:33(UTC)
Евгений Афанасьев

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

Группы: Участники
Зарегистрирован: 06.12.2008(UTC)
Сообщений: 3,910
Российская Федерация
Откуда: Крипто-Про

Сказал(а) «Спасибо»: 20 раз
Поблагодарили: 685 раз в 646 постах
Да, строится на вашем компьютере.
В сертификате может быть информация о сертификате УЦ, например, в клиентском сертификате ссылка на промежуточный, а может не быть, ссылка может быть рабочая, а может не работать. В любом случае промежуточный должен быть каким-то образом достижим: либо скачан отдельно (в виде файла) и передан в параметр cpp перед build, либо не скачан, но доступен по ссылке в предыдущем сертификате при включенном параметре enableAIAcaIssuers. Надежнее, пожалуй, скачать/закешировать промежуточный.
Кстати, keyStore.getCertificateChain() вернет список сертификатов (цепочку) из ключевого контейнера, только если цепочка была туда установлена (такое бывает нечасто).

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

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