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

Уведомление

Icon
Error

Опции
К последнему сообщению К первому непрочитанному
Offline Grandma$ter  
#1 Оставлено : 30 ноября 2022 г. 9:21:48(UTC)
Grandma$ter

Статус: Новичок

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

Доброе время суток.
Есть необходимость перевести уже рабочую систему на более новую jcp.


Было:
Рабочая интеграция с ГИС ЖКХ, включающая в себя jcp 2.0.39014, java 8, wildfly 10.

Были предприняты попытки просто подменить библиотеку и запустить все под 11 java.
Так или иначе это приводило к выбрасыванию исключения на этапе подписи или отправки(одна из последних ошибок, это NullPointerException внутри проверки jcp своих же jar'ников)


На данный момент:
Используются: wildfly 15, jcp-2.0.41940-A и java 11. jcp-2.0.41940-A в wildfly вынесен в модули.

Основные проблемы были на этапе подключения провейдеров и получения socketFactory из SSLContext. Собственно, эти участки и постарался изменить в соответствии с примерами кода из либы.

Фрагмент кода добавления провайдеров/получения фабрики сокетов


Далее gostSSLSocketFactory используется в наследнике java.net.URLStreamHandler, где переопределяется метод openConnection:


В окружении wildfly стоит tls_prohibit_disabled_validation = false. Т.к. были проблемы при handShake.



В итоге мы отправляем SOAP запрос и получем ответ с сервера ГИС ЖКХ. В ответе присутствует стэктрейс и ошибка такого характера:
"Certificate in header is blank: ru.lanit.hcs.integration.common.exception.SoapFaultException: Certificate in header is blank".

Было подозрение, что криво заполняется body Soap запроса. В итоге сравнил xml текущую и ту, которая создается на прошлой реализации jcp(2.0.39014) и java(8) - отличий не заметил.
Когда снифили пакеты, то заметили отличие только в TLS в запросах. В случае со старой реализацией улетает tls1.0, а в текущей tls1.2.

В чем может быть проблема? Что за заголовок с сертификатом им может быть нужен и почему он пустой?



Offline Евгений Афанасьев  
#2 Оставлено : 1 декабря 2022 г. 17:33:52(UTC)
Евгений Афанасьев

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

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

Сказал(а) «Спасибо»: 20 раз
Поблагодарили: 704 раз в 665 постах
Здравствуйте.
SOAP и TLS - разные несвязанные протоколы. Ошибка вида "Certificate in header is blank: ru.lanit.hcs.integration.common.exception.SoapFaultException: Certificate in header is blank" относится к первому. вероятно, что-то не так в структуре документа (не добавлен какой-то сертификат в header сообщения).
Если вы указали протокол "GostTLS", то будет TLSv1, если "GostTLSv1.2" - TLSv.1.2.
Offline Grandma$ter  
#3 Оставлено : 19 декабря 2022 г. 12:30:51(UTC)
Grandma$ter

Статус: Новичок

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

Проблема решилась заменой TLSContext.initClientSSL на sslContext.init.

Код:

System.setProperty("javax.net.ssl.keyStoreType", Consts.KeyStoreType);
System.setProperty("javax.net.ssl.keyStorePassword", Consts.KeyStorePassword);
System.setProperty("javax.net.ssl.trustStoreType", Consts.KeyStoreTrustedType);
System.setProperty("javax.net.ssl.trustStore", Consts.KeyStoreTrustedFile);
System.setProperty("javax.net.ssl.trustStorePassword", Consts.KeyStoreTrustedPassword);
System.setProperty("javax.net.debug", "ssl");

Security.addProvider(new JCP()); // JCP
Security.addProvider(new CryptoProvider()); // JCryptoP
Security.addProvider(new RevCheck()); // RevCheck
Security.addProvider(new Provider());

keyStore = KeyStore.getInstance(JCP.HD_STORE_NAME);
KeyManagerFactory kf = KeyManagerFactory.getInstance("GostX509");

keyStore.load(null, Consts.KeyStorePassword.toCharArray());
kf.init(keyStore, Consts.KeyStorePassword.toCharArray());

privateKey = (PrivateKey) keyStore.getKey(Consts.KeyAlias, Consts.KeyStorePassword.toCharArray());
cert = (X509Certificate) keyStore.getCertificate(Consts.KeyAlias);

TrustManagerFactory tf = TrustManagerFactory.getInstance("GostX509");

trustStore = KeyStore.getInstance(Consts.KeyStoreTrustedType, Consts.KeyStoreTrustedProvider);
trustStore.load(new FileInputStream(new File(Consts.KeyStoreTrustedFile)), Consts.KeyStoreTrustedPassword.toCharArray());

tf.init(trustStore);

sslContext.init(kf.getKeyManagers(), tf.getTrustManagers(), null);

gostSSLSocketFactory = sslContext.getSocketFactory();


Если честно, не до конца понял в чем разница, т.к. TLSContext.initClientSSL внутри тоже создает KeyManagerFactory и т.п.



Теперь с гиса возвращается успешный ответ, но при проверке подписи вылетает исключение: "urn:getState: The referenced SignedProperties are not contained by the proper QualifyingProperties element: ru.tii.crypto.core.SignException: The referenced SignedProperties are not contained by the proper QualifyingProperties element"
В ответе ГИСа нету ошибок, т.к. эти же ответы нормально проходят проверку подписи на старой реализации. И SignedProperties находится внутри QualifyingProperties.


Ниже привожу код проверки, который работает на старой реализации(jcp 2.0.39014, java 8) и не работает на новой(jcp 2.0.41940-A, java 11):
Код:

final Document verifyDocument = msg.getSOAPPart().getEnvelope().getOwnerDocument();

final NodeList nl = verifyDocument.getElementsByTagNameNS(XMLSignature.XMLNS, "Signature");

if (nl.getLength() == 0) {
	return;
}


MessageDigestEngineProvider messageDigestEngineProvider = new CustomizableMessageDigestEngineProvider();

	        
CertificateValidationProvider certValidator = KeyStoreUtils.createCertificateValidationProvider(GostConfig.trustStore);
	        
	        
			
XadesVerificationProfile vp = new XadesVerificationProfile(certValidator);
vp.withBinding(MessageDigestEngineProvider.class, messageDigestEngineProvider);
vp.withBinding(QualifyingPropertiesUnmarshaller.class, QualifyingPropertiesUnmarshaller2.class);
vp.withQualifyingPropertyVerifier(SigningTimeData.class, NoSigningTimeVerifier.class);
vp.withQualifyingPropertyVerifier(SigningCertificateData.class, SigningCertificateVerifier2.class);
	        

	        
for (int i = 0; i < nl.getLength(); i++) {
	        	
	final XadesVerifier verifier = vp.newVerifier();
	            
	final SignatureSpecificVerificationOptions verificationOptions = new SignatureSpecificVerificationOptions();
	final Element signatureElement = (Element) nl.item(i);
	XAdESVerificationResult vr = verifier.verify(signatureElement, verificationOptions);
}

Offline Евгений Афанасьев  
#4 Оставлено : 19 декабря 2022 г. 16:00:19(UTC)
Евгений Афанасьев

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

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

Сказал(а) «Спасибо»: 20 раз
Поблагодарили: 704 раз в 665 постах
Здравствуйте.
А "ru.tii.crypto.core.SignException" - это чей ответ?
Приведенный код, предполагаю, относится к xades4j, а JCP только проверяет хэши и подписи.
Offline Grandma$ter  
#5 Оставлено : 19 декабря 2022 г. 17:26:33(UTC)
Grandma$ter

Статус: Новичок

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

Автор: Евгений Афанасьев Перейти к цитате
Здравствуйте.
А "ru.tii.crypto.core.SignException" - это чей ответ?
Приведенный код, предполагаю, относится к xades4j, а JCP только проверяет хэши и подписи.


SignException - наша обертка над исключением. Изначально там вылетает xades4j.verification.QualifyingPropertiesIncorporation. Выбрасывается оно при вызове SignatureUtils.checkSignedPropertiesIncorporation. Код следующий:

Код:

static void checkSignedPropertiesIncorporation(Element qualifyingPropsElem, Reference signedPropsRef) throws QualifyingPropertiesIncorporationException
    {
        Element signedPropsElem = DOMHelper.getFirstChildElement(qualifyingPropsElem);
        if (signedPropsElem == null
                || !signedPropsElem.getLocalName().equals(QualifyingProperty.SIGNED_PROPS_TAG)
                || !signedPropsElem.getNamespaceURI().equals(QualifyingProperty.XADES_XMLNS))
        {
            throw new QualifyingPropertiesIncorporationException("SignedProperties not found as the first child of QualifyingProperties.");
        }

        DOMHelper.useIdAsXmlId(signedPropsElem);

        // Only QualifyingProperties in the signature's document are supported.
        // XML-DSIG 4.3.3.2: "a same-document reference is defined as a URI-Reference
        // that consists of a hash sign ('#') followed by a fragment"
        if (!signedPropsRef.getURI().startsWith("#"))
        {
            throw new QualifyingPropertiesIncorporationException("Only QualifyingProperties in the signature's document are supported");
        }

        try
        {
            Node sPropsNode = signedPropsRef.getNodesetBeforeFirstCanonicalization().getSubNode();
            if (sPropsNode == null || sPropsNode.getNodeType() != Node.ELEMENT_NODE)
            {
                throw new QualifyingPropertiesIncorporationException("The supposed reference over signed properties doesn't cover an element.");
            }

            // The referenced signed properties element must be the child of qualifying properties.
            Element referencedSignedPropsElem = (Element) sPropsNode;
            if (referencedSignedPropsElem != signedPropsElem)
            {
                throw new QualifyingPropertiesIncorporationException("The referenced SignedProperties are not contained by the proper QualifyingProperties element");
            }
        } catch (XMLSignatureException ex)
        {
            throw new QualifyingPropertiesIncorporationException("Cannot get the referenced SignedProperties", ex);
        }
    }


В итоге referencedSignedPropsElem != signedPropsElem, хотя signedPropsElem внутри себя включает объект, на который ссылается referencedSignedPropsElem.
Мог ли jcp как-то повлиять на ход этой проверки?
Версию xades4j не меняли. При запуске старой версии приложения таких ошибок нету.
RSS Лента  Atom Лента
Пользователи, просматривающие эту тему
Guest (2)
Быстрый переход  
Вы не можете создавать новые темы в этом форуме.
Вы не можете отвечать в этом форуме.
Вы не можете удалять Ваши сообщения в этом форуме.
Вы не можете редактировать Ваши сообщения в этом форуме.
Вы не можете создавать опросы в этом форуме.
Вы не можете голосовать в этом форуме.