Статус: Активный участник
Группы: Участники
Зарегистрирован: 05.08.2019(UTC) Сообщений: 65
Сказал(а) «Спасибо»: 4 раз
|
Добрый день! Имеется КриптоПро JCP и CSP. В CSP существует добавлен контейнер с алиасом внутри которого находится личный сертификат и приватный ключ. Проблема в том, что сертификат только один и доверия к нему нет. Соответственно, во время создания открепленной подписи добавляется только один сертификат. Как мы можем импортировать еще один сертификат, чтобы когда мы вызываем нативный java метод Цитата:keyStore.getCertificateChain(String alias) По данному алиасу находились как и сертификат подписанта, так и выщестоящие сертификаты для того, чтобы позже добавить их в подпись Заранее спасибо Отредактировано пользователем 9 декабря 2019 г. 9:56:08(UTC)
| Причина: Не указана
|
|
|
|
Статус: Сотрудник
Группы: Участники
Зарегистрирован: 06.12.2008(UTC) Сообщений: 4,006  Откуда: Крипто-Про Сказал(а) «Спасибо»: 21 раз Поблагодарили: 715 раз в 675 постах
|
Здравствуйте. Автор: 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)
| Причина: Не указана |
|
|
|
|
Статус: Активный участник
Группы: Участники
Зарегистрирован: 05.08.2019(UTC) Сообщений: 65
Сказал(а) «Спасибо»: 4 раз
|
А возможно добавить сразу их в keyStore java, а потом вызывать метод keyStore.getCertificateChain(String alias) и в нем сразу будут все сертификаты? Т.е. нужно в keyStore JCP "HDImageStore" добавить сертификат с тем же алиасом, но без контейнера, т.к. нет приватного ключа
|
|
|
|
Статус: Эксперт
Группы: Участники
Зарегистрирован: 05.03.2015(UTC) Сообщений: 1,602  Откуда: Иркутская область Сказал(а) «Спасибо»: 110 раз Поблагодарили: 395 раз в 366 постах
|
|
|
|
|
Статус: Сотрудник
Группы: Участники
Зарегистрирован: 06.12.2008(UTC) Сообщений: 4,006  Откуда: Крипто-Про Сказал(а) «Спасибо»: 21 раз Поблагодарили: 715 раз в 675 постах
|
Автор: rmussalimov  А возможно добавить сразу их в keyStore java, а потом вызывать метод keyStore.getCertificateChain(String alias) и в нем сразу будут все сертификаты? Т.е. нужно в keyStore JCP "HDImageStore" добавить сертификат с тем же алиасом, но без контейнера, т.к. нет приватного ключа Да, если построить цепочку и с помощью keyStore.setCertificateEntry добавить цепочку в контейнер. Тогда в расширения в контейнере попадут промежуточные и корневой сертификаты. После этого keyStore.getCertificateChain() станет возвращать каждый раз цепочку. |
|
|
|
|
Статус: Активный участник
Группы: Участники
Зарегистрирован: 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) "цепочку" и все типо работает. Хотя размер файла увеличился, сначала думал, что хороший знак, но все сервисы проверок "видят" только сертификат подписанта. Подскажите, пожалуйста, куда копать
|
|
|
|
Статус: Сотрудник
Группы: Участники
Зарегистрирован: 06.12.2008(UTC) Сообщений: 4,006  Откуда: Крипто-Про Сказал(а) «Спасибо»: 21 раз Поблагодарили: 715 раз в 675 постах
|
Автор: rmussalimov  Начинаю сомневаться, что так можно делать (просто добавлять в cms.certificates) "цепочку" и все типо работает. Хотя размер файла увеличился, сначала думал, что хороший знак, но все сервисы проверок "видят" только сертификат подписанта.
certificates как раз предназначен для того, чтобы передать те сертификаты, которые могут быть использованы при проверке подписи. Например, может быть включен один сертификат подписи для проверки подписи, если у проверяющей стороны его нет. Другие сертификаты также могут быть добавлены и использованы проверяющей стороной (если это требуется проверяющей стороной) на свое усмотрение (например, для построения и проверки цепочки сертификатов подписанта). Также в подписи могут быть и CRL'и (для проверки цепочки сертификатов, если такое предусмотрено и требуется проверяющей стороной). |
|
|
|
|
Статус: Активный участник
Группы: Участники
Зарегистрирован: 05.08.2019(UTC) Сообщений: 65
Сказал(а) «Спасибо»: 4 раз
|
То есть никак не добавить промежуточные и корневые сертификаты?
|
|
|
|
Статус: Сотрудник
Группы: Участники
Зарегистрирован: 06.12.2008(UTC) Сообщений: 4,006  Откуда: Крипто-Про Сказал(а) «Спасибо»: 21 раз Поблагодарили: 715 раз в 675 постах
|
Вы ведь добавили, судя по коду, в подпись. Про контейнер я писал ранее: если надо добавить в него, то постройте цепочку и выполните setCertificateEntry на контейнере, промежуточные и корневые установятся в расширения контейнера. |
|
|
|
|
Статус: Активный участник
Группы: Участники
Зарегистрирован: 05.08.2019(UTC) Сообщений: 65
Сказал(а) «Спасибо»: 4 раз
|
|
|
|
|
Быстрый переход
Вы не можете создавать новые темы в этом форуме.
Вы не можете отвечать в этом форуме.
Вы не можете удалять Ваши сообщения в этом форуме.
Вы не можете редактировать Ваши сообщения в этом форуме.
Вы не можете создавать опросы в этом форуме.
Вы не можете голосовать в этом форуме.
Important Information:
The Форум КриптоПро uses cookies. By continuing to browse this site, you are agreeing to our use of cookies.
More Details
Close