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

Уведомление

Icon
Error

2 Страницы12>
Опции
К последнему сообщению К первому непрочитанному
Offline rmussalimov  
#1 Оставлено : 9 декабря 2019 г. 9:55:35(UTC)
rmussalimov

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

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

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

Имеется КриптоПро JCP и CSP.

В CSP существует добавлен контейнер с алиасом внутри которого находится личный сертификат и приватный ключ.

Проблема в том, что сертификат только один и доверия к нему нет.

Соответственно, во время создания открепленной подписи добавляется только один сертификат.

Как мы можем импортировать еще один сертификат, чтобы когда мы вызываем нативный java метод

Цитата:
keyStore.getCertificateChain(String alias)


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

Заранее спасибо

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

Offline Евгений Афанасьев  
#2 Оставлено : 9 декабря 2019 г. 11:01:43(UTC)
Евгений Афанасьев

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

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

Сказал(а) «Спасибо»: 20 раз
Поблагодарили: 685 раз в 646 постах
Здравствуйте.
Автор: rmussalimov Перейти к цитате


Имеется КриптоПро JCP и CSP.

В CSP существует добавлен контейнер с алиасом внутри которого находится личный сертификат и приватный ключ.

Проблема в том, что сертификат только один и доверия к нему нет.

Соответственно, во время создания открепленной подписи добавляется только один сертификат.

Как мы можем импортировать еще один сертификат, чтобы когда мы вызываем нативный java метод

Цитата:
keyStore.getCertificateChain(String alias)


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

Заранее спасибо

До того, как сертификат(ы) попал(и) в контейнер, это можно сделать, получив в УЦ, который выпустил сертификат подписи, всю цепочку в формате p7b и установив еще в контейнер (в панели управления JCP или программно с помощью keyStore.setCertificateEntry(alias, certs[])).
Если контейнер уже есть и в нем один сертификат подписи, а нужна вся цепочка, то остается один путь: построить ее. На форуме это уже неоднократно описывалось, можно поискать по слову enableAIAcaIssuers.
Как построить цепочку, можно увидеть в примере CRLValidateCert в userSamples в samples-sources.jar в дистрибутиве jcp.
Обязательным является список доверенных корневых и target-сертификат (для которого строим цепочку, сертификат подписи). Все некорневые сертификаты можно поместить в список и передать в параметры в addCertStore. Если в сертификате подписи есть ссылки на промежуточный сертификат и есть доступ в сеть, то этот сертификат (как и другие, кроме корневого) может быть скачан, если включена настройка:
Код:

System.setProperty("com.sun.security.enableAIAcaIssuers", "true");
System.setProperty("ru.CryptoPro.reprov.enableAIAcaIssuers", "true");

Бывает, что ссылок (или/и доступа) нет, тогда промежуточные придется качать и хранить отдельно и передавать их в addCertStore.

Отредактировано пользователем 9 декабря 2019 г. 11:03:00(UTC)  | Причина: Не указана

Offline rmussalimov  
#3 Оставлено : 9 декабря 2019 г. 11:21:33(UTC)
rmussalimov

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

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

Сказал(а) «Спасибо»: 4 раз
А возможно добавить сразу их в keyStore java, а потом вызывать метод keyStore.getCertificateChain(String alias) и в нем сразу будут все сертификаты? Т.е. нужно в keyStore JCP "HDImageStore" добавить сертификат с тем же алиасом, но без контейнера, т.к. нет приватного ключа
Offline two_oceans  
#4 Оставлено : 9 декабря 2019 г. 12:37:36(UTC)
two_oceans

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

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

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

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

Offline Евгений Афанасьев  
#5 Оставлено : 9 декабря 2019 г. 13:16:32(UTC)
Евгений Афанасьев

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

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

Сказал(а) «Спасибо»: 20 раз
Поблагодарили: 685 раз в 646 постах
Автор: rmussalimov Перейти к цитате
А возможно добавить сразу их в keyStore java, а потом вызывать метод keyStore.getCertificateChain(String alias) и в нем сразу будут все сертификаты? Т.е. нужно в keyStore JCP "HDImageStore" добавить сертификат с тем же алиасом, но без контейнера, т.к. нет приватного ключа

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

Offline rmussalimov  
#6 Оставлено : 10 декабря 2019 г. 9:54:26(UTC)
rmussalimov

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

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

Сказал(а) «Спасибо»: 4 раз
Спасибо большое за ответ.

Выяснилось, что у нас очень много "движущихся частей", поэтому менять то, что возвращает keyStore довольно опасно.

Необходимо каким-то другим образом генерировать pkcs7 подпись таким образом, чтобы внутри была цепочка. В итоге модифицировал метод из CMS_samples.CMS#CMSSign(byte[],
* PrivateKey, Certificate, boolean


Теперь он выглядит так:

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


boolean isChainPresentAndNotEmpty = chainCertificates != null && chainCertificates.length > 0;

if (isChainPresentAndNotEmpty) // Цепочка есть, размер равен кол-во эл-ов + 1 (серт подписанта)
{
cms.certificates = new CertificateSet(chainCertificates.length + 1);
cms.certificates.elements = new CertificateChoices[chainCertificates.length + 1];
}
else // Если нет, то в подписи только сертификат подписанта
{
cms.certificates = new CertificateSet(1);
cms.certificates.elements = new CertificateChoices[1];
}

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

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

final Asn1BerDecodeBuffer decodeSignerBuffer =
new Asn1BerDecodeBuffer(certificate.getEncoded());
asnSignerCertificate.decode(decodeSignerBuffer);

//cms.certificates.elements = new CertificateChoices[1];

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

// Добавляем цепочные сертификаты в подпись

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

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

//cms.certificates.elements = new CertificateChoices[1];

cms.certificates.elements[i + 1] = new CertificateChoices();
cms.certificates.elements[i + 1].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();
}


В общем, certificate это сертификат подписанта (который всегда включается в подпись без проблем) а chainCertificates это сертификаты уровнем выше (т.е. промежуточный1 -> промежуточный2 -> ... -> корневой).

Начинаю сомневаться, что так можно делать (просто добавлять в cms.certificates) "цепочку" и все типо работает. Хотя размер файла увеличился, сначала думал, что хороший знак, но все сервисы проверок "видят" только сертификат подписанта.

Подскажите, пожалуйста, куда копать
Offline Евгений Афанасьев  
#7 Оставлено : 10 декабря 2019 г. 10:23:12(UTC)
Евгений Афанасьев

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

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

Сказал(а) «Спасибо»: 20 раз
Поблагодарили: 685 раз в 646 постах
Автор: rmussalimov Перейти к цитате

Начинаю сомневаться, что так можно делать (просто добавлять в cms.certificates) "цепочку" и все типо работает. Хотя размер файла увеличился, сначала думал, что хороший знак, но все сервисы проверок "видят" только сертификат подписанта.

certificates как раз предназначен для того, чтобы передать те сертификаты, которые могут быть использованы при проверке подписи. Например, может быть включен один сертификат подписи для проверки подписи, если у проверяющей стороны его нет. Другие сертификаты также могут быть добавлены и использованы проверяющей стороной (если это требуется проверяющей стороной) на свое усмотрение (например, для построения и проверки цепочки сертификатов подписанта). Также в подписи могут быть и CRL'и (для проверки цепочки сертификатов, если такое предусмотрено и требуется проверяющей стороной).
Offline rmussalimov  
#8 Оставлено : 10 декабря 2019 г. 10:58:44(UTC)
rmussalimov

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

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

Сказал(а) «Спасибо»: 4 раз
То есть никак не добавить промежуточные и корневые сертификаты?
Offline Евгений Афанасьев  
#9 Оставлено : 10 декабря 2019 г. 11:09:08(UTC)
Евгений Афанасьев

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

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

Сказал(а) «Спасибо»: 20 раз
Поблагодарили: 685 раз в 646 постах
Вы ведь добавили, судя по коду, в подпись. Про контейнер я писал ранее: если надо добавить в него, то постройте цепочку и выполните setCertificateEntry на контейнере, промежуточные и корневые установятся в расширения контейнера.
Offline rmussalimov  
#10 Оставлено : 10 декабря 2019 г. 11:13:47(UTC)
rmussalimov

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

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

Сказал(а) «Спасибо»: 4 раз
Нужно добавить именно в подпись. И каким образом низкоуровневый ASN поймет, что включается вся цепочка вместо одного сертификата? Я ожидаю что-то наподобие этого https://stackoverflow.co...ms-container-in-c-sharp.

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