ty134 |
|
Статус: Участник Группы: Участники
|
Добрый день! Подписываю: Код:
передаю в СМЭВ 3: Outbound message: Код:
код для Java Код:
В результате ошибка: Не совсем понятно, данные которые подписывались, не соответствуют данным которые проверяются, или содержимое блока ds:Signature не соответствует требованиям СМЭВ-3. Подскажите что делаю не так, пожалуйста. читаемые XML на подпись Код:
в СМЭВ-3 Код:
|
|
|
ty134 |
|
Статус: Участник Группы: Участники
|
сравнил с эталонным примером, убрал Код:
результат не изменился Код:
Код:
|
|
|
daniil.g |
|
Статус: Новичок Группы: Участники
|
Автор: ty134 Подскажите что делаю не так, пожалуйста. Попробуйте проверить алгоритм формирования хэша и подписи по этой статье: http://blog.gin.su/ |
|
|
ty134 |
|
Статус: Участник Группы: Участники
|
Цитата: 4. Общее описание процесса работы СМЭВ3 расписано в методических рекоммендациях Daniil, что то не соображу: (очень надеюсь на Ваш ответ) у меня есть раздел(Element) xml, который находится в SenderProvidedRequestData, мне нужно его подписать и подпись положить в CallerInformationSystemSignature. Вариант первый: Вариант второй: Какой вариант правильный? Если верен Первый вариант, то про JAXB и требования возможности генерации клиента стандартными средствами (заявленными в СМЭВ 3, если не ошибаюсь), можно забыть и совершенно понятна ошибка, я ей передаю данные до преобразования, а подписываю после преобразования. …………………………………………………………………………………………………………………………….. Вариант 1 — собрал по частям CNTR-C, CNTR-C в блокноте — на стенде все ОК Код:
Вариант 2 — здесь все программа сгенерировала — на стенде все ОК Код:
Отредактировано пользователем 28 февраля 2018 г. 11:01:41(UTC) |
|
|
ty134 |
|
Статус: Участник Группы: Участники
|
нашел пример на основе, но результат тот же https://github.com/vladk1m0/smevx-crypto |
|
|
Евгений Афанасьев |
|
Статус: Сотрудник Группы: Участники Сказал(а) «Спасибо»: 20 раз |
Отличная статья про СМЭВ3+Java Отредактировано пользователем 28 февраля 2018 г. 16:02:55(UTC) |
Тех. поддержка |
|
|
|
ty134 |
|
Статус: Участник Группы: Участники
|
взял пример SendRequestRequestNoAttach.xml прогоняю на портале: Код:
|
|
|
ty134 |
|
Статус: Участник Группы: Участники
|
Ой не, все нормально, огромное спасибо VBurmistrov |
|
|
Andefraim |
|
Статус: Новичок Группы: Участники
|
Ошибка «ЭП-ОВ не соответствует подписанным данным: Ошибка проверки ЭП: Нарушена целостность ЭП» Алгоритм подписания Код:
Результат подписания Код:
На портале (https://smev3.gosuslugi.ru/portal/checkxmlform.jsp) проходит проверку с результатом «ЭЦП подтвержена». Код:
Как успешно отправить запрос в СМЭВ 3? |
|
|
accessx |
|
Статус: Новичок Группы: Участники
|
Автор: ty134 взял пример SendRequestRequestNoAttach.xml прогоняю на портале: У меня тоже на данном примере возникает ошибка проверки ЭП, хотя DigestValue тоже равен /jXl70XwnttJB5sSokwh8SaVHwo2gjgILSu0qBaLUAo=. Вы пишите, что у вас всё ОК. Как вы этого добились, с чем была связана ошибка? |
|
|
Пользователи, просматривающие эту тему |
Guest |
Быстрый переход
Вы не можете создавать новые темы в этом форуме.
Вы не можете отвечать в этом форуме.
Вы не можете удалять Ваши сообщения в этом форуме.
Вы не можете редактировать Ваши сообщения в этом форуме.
Вы не можете создавать опросы в этом форуме.
Вы не можете голосовать в этом форуме.
Вопрос: После отправки отчета в ПФР пришла критическая ошибка — Нарушена целостность ЭЦП
15.01.2018 10:09
2 345
Решение вопроса:
Если протокол положительный, на ошибку можно не обращать внимания.
Ошибка чаще всего связана с тем, что в момент отправки отчета были какие-то работы на сервере ПФР (например добавляли новые сертификаты или просто планово перезагружались). Соответственно, приемный комплекс не сразу смог прочитать информацию о корректности ЭП.
Эта информация оказалась полезной?
Как можно улучшить этот ответ?
Время на прочтение
16 мин
Количество просмотров 42K
Система межведомственного электронного взаимодействия (СМЭВ) задумывалась как цифровая среда предоставления услуг и исполнения государственных и муниципальных функций в электронной форме.
В настоящее время СМЭВ продолжает расширять свои возможности и вовлекать все большее количество участников взаимодействия.
Что оказалось как нельзя кстати, в том числе для коммерческих организаций, в частности банков, которые все больше стремятся перевести свои услуги в цифру и сериализовать процессы.
В этой статье мы поговорим о том, как своими силами подписать запросы и проверить электронные подписи ответов СМЭВ версии 3.0, и о паре интересных нюансов, с которыми пришлось при этом столкнуться.
Здравствуйте!
Может возникнуть вопрос. Почему своими силами? Когда для СМЭВ 3 есть целый Технологический портал, где
- опубликована вся документация и методические указания,
- есть раздел с часто задаваемыми вопросами,
- можно скачать актуальную версию библиотек клиента СМЭВ 3,
- предоставлены примеры полных конвертов сообщений с подписями,
- можно даже проверить онлайн свое сообщение или из примера на соответствие схемам сервиса СМЭВ и на предмет валидности его электронной подписи
Все верно, портал, безусловно, крайне полезный, и всеми его подсказками и инструментами можно и нужно пользоваться, но вот код на Java напишем свой.
По той простой причине, что уже есть собственная информационная система, работающая с форматами электронной подписи XMLDSig, XAdES, в которой применяются библиотеки проекта Apache Santuario, реализующие основные стандарты безопасности для XML. А также библиотеки, входящие в состав КриптоПро JCSP, помимо работы с XML, обеспечивающие API криптографических функций СКЗИ КриптоПро CSP.
Написание собственных методов для работы с электронными подписями СМЭВ 3 в данном случае выглядит более целесообразно, нежели разворачивание полного клиента поставляемого:
ФГБУ НИИ «Восход» (до 21 марта 2016 года ФГУП НИИ «Восход») или интеграция, его отдельных классов и пакетов.
В то же время заглянуть в открытый код клиента всегда полезно, а его наличие само по себе говорит о зрелости системы и высоком уровне поддержки.
Анализ исходных данных
Загружаем с портала СМЭВ 3:
- актуальную версию документа Методические рекомендации по работе с ЕСМЭВ версия 3.4.0.3
- примеры полных конвертов сообщений, отправляемых в СМЭВ 3
Если уже умеем формировать обычный XMLDSig или подписывать, например, конверты сообщений СМЭВ 2, то больше всего начинает интересовать, чем же отличается конверт с подписью СМЭВ 3 от СМЭВ 2.
Открываем пример конверта СМЭВ 3 SendRequestRequestNoAttach.xml
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns="urn://x-artefacts-smev-gov-ru/services/message-exchange/types/1.1">
<S:Body>
<ns2:SendRequestRequest xmlns:ns3="urn://x-artefacts-smev-gov-ru/services/message-exchange/types/faults/1.1" xmlns:ns2="urn://x-artefacts-smev-gov-ru/services/message-exchange/types/1.1" xmlns="urn://x-artefacts-smev-gov-ru/services/message-exchange/types/basic/1.1">
<ns:SenderProvidedRequestData Id="SIGNED_BY_CONSUMER" xmlns="urn://x-artefacts-smev-gov-ru/services/message-exchange/types/1.1" xmlns:ns="urn://x-artefacts-smev-gov-ru/services/message-exchange/types/1.1" xmlns:ns2="urn://x-artefacts-smev-gov-ru/services/message-exchange/types/basic/1.1"> <ns:MessageID>db0486d0-3c08-11e5-95e2-d4c9eff07b77</ns:MessageID><ns2:MessagePrimaryContent><ns1:BreachRequest xmlns:ns1="urn://x-artefacts-gibdd-gov-ru/breach/root/1.0" xmlns:ns2="urn://x-artefacts-gibdd-gov-ru/breach/commons/1.0" xmlns:ns3="urn://x-artefacts-smev-gov-ru/supplementary/commons/1.0.1" Id="PERSONAL_SIGNATURE"> <ns1:RequestedInformation> <ns2:RegPointNum>Т785ЕС57</ns2:RegPointNum> </ns1:RequestedInformation> <ns1:Governance> <ns2:Name>ГИБДД РФ</ns2:Name> <ns2:Code>GIBDD</ns2:Code> <ns2:OfficialPerson> <ns3:FamilyName>Загурский</ns3:FamilyName> <ns3:FirstName>Андрей</ns3:FirstName> <ns3:Patronymic>Петрович</ns3:Patronymic> </ns2:OfficialPerson></ns1:Governance> </ns1:BreachRequest> </ns2:MessagePrimaryContent> <ns:TestMessage/></ns:SenderProvidedRequestData>
<ns2:CallerInformationSystemSignature><ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"><ds:SignedInfo><ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/><ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#gostr34102001-gostr3411"/><ds:Reference URI="#SIGNED_BY_CONSUMER"><ds:Transforms><ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/><ds:Transform Algorithm="urn://smev-gov-ru/xmldsig/transform"/></ds:Transforms><ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#gostr3411"/><ds:DigestValue>/jXl70XwnttJB5sSokwh8SaVHwo2gjgILSu0qBaLUAo=</ds:DigestValue></ds:Reference></ds:SignedInfo><ds:SignatureValue>J3746ks34pOcPGQpKzc0sz3n9+gjPtzZbSEEs4c3sTwbtfdaY7N/hxXzEIvXc+3ad9bc35Y8yBhZ/BYbloGt+Q==</ds:SignatureValue><ds:KeyInfo><ds:X509Data><ds:X509Certificate>MIIBcDCCAR2gAwIBAgIEHVmVKDAKBgYqhQMCAgMFADAtMRAwDgYDVQQLEwdTWVNURU0xMQwwCgYDVQQKEwNJUzIxCzAJBgNVBAYTAlJVMB4XDTE1MDUwNzEyMTUzMFoXDTE4MDUwNjEyMTUzMFowLTEQMA4GA1UECxMHU1lTVEVNMTEMMAoGA1UEChMDSVMyMQswCQYDVQQGEwJSVTBjMBwGBiqFAwICEzASBgcqhQMCAiMBBgcqhQMCAh4BA0MABEDoWGZlTUWD43G1N7TEm14+QyXrJWProrzoDoCJRem169q4bezFOUODcNooQJNg3PtAizkWeFcX4b93u8fpVy7RoyEwHzAdBgNVHQ4EFgQUaRG++MAcPZvK/E2vR1BBl5G7s5EwCgYGKoUDAgIDBQADQQCg25vA3RJL3kgcJhVOHA86vnkMAtZYr6HBPa7LpEo0HJrbBF0ygKk50app1lzPdZ5TtK2itfmNgTYiuQHX3+nE</ds:X509Certificate></ds:X509Data></ds:KeyInfo></ds:Signature></ns2:CallerInformationSystemSignature>
</ns2:SendRequestRequest>
</S:Body>
</S:Envelope>
Дедуктивным методом выясняется что:
- больше не используется прием с выносом из содержимого тега Signature в Security заголовок элемента BinarySecurityToken с сертификатом открытого ключа проверки электронной подписи и ссылкой на него через SecurityTokenReference в теле самого Signature, как, например, в СМЭВ 2.4.6. Теперь сертификат должен находиться внутри Signature.
- второе и, по сути, самое существенное и важное изменение, оказывающее большое влияние на процесс подписи — это добавление новой проприетарной трансформации:
<ds:Transform Algorithm="urn://smev-gov-ru/xmldsig/transform"/>
Через эту трансформацию распространяются собственные правила каноникализации СМЭВ 3.
Каноникализация — процесс приведения данных, имеющих несколько возможных форм представления, к одному нормализованному стандартному виду.
Перед тем как посчитать хэш подписываемого атрибута в XML-конверте и подписать, необходимо выполнить его конвертацию в заданный правилами СМЭВ 3 вид.
В поисках описания трансформации urn://smev-gov-ru/xmldsig/transform открываем Методические рекомендации 3.4.0.3
Знакомимся с пунктом 4.4.2.1 Правила формирования электронной подписи сообщений
Формат подписи XMLDSig detached (https://www.w3.org/TR/xmldsig-core/)
Трансформация, дополнительно к канонизации urn://smev-gov-ru/xmldsig/transform
Требования к форматированию В XML-структуре подписи между элементами не допускается наличие текстовых узлов, в том числе переводов строки.
Пункт Методических указаний 12.4. ПРИЛОЖЕНИЕ 4: ОБРАЗЦОВАЯ РЕАЛИЗАЦИЯ ТРАНСФОРМАЦИИ URN://SMEV-GOV-RU/XMLDSIG/TRANSFORM
содержит Java класс SmevTransformSpi.java, реализующий алгоритм трансформации «urn://smev-gov-ru/xmldsig/transform», наследник org.apache.xml.security.transforms.TransformSpi из библиотеки Apache Santuario.
Таким образом, чтобы обеспечить каноникализацию подписываемого конверта СМЭВ 3, можно использовать в своем коде этот класс трансформации.
Единственным условием и ограничением в этом случае будет, что для обработки XML-документа при формировании подписи или ее проверки нужно использовать именно org.apache.xml.security.signature.XMLSignature из проекта Apache Santuario.
Задействовать инструменты из пакетов javax.xml.crypto.dsig или ru.CryptoPro.JCPxml.xmldsig просто так уже не получится.
Подготовка к подписи по правилам СМЭВ 3
Apache Santuario изначально ничего не знает про ГОСТ криптографические алгоритмы и СКЗИ КриптоПро.
В библиотеке xmlsec-1.5.0.jar в файле orgapachexmlsecurityresourceconfig.xml содержатся настройки только для работы с зарубежными криптографическими алгоритмами.
Чтобы он начал распознавать и применять ГОСТ, нужно выполнить его инициализацию.
По старинке это делалось так:
//APACHE-SANTUARIO INIT WITH CryptoPro JCP
System.setProperty("org.apache.xml.security.resource.config", "resource/jcp.xml");
org.apache.xml.security.Init.init();
String cfile1 = System.getProperty("org.apache.xml.security.resource.config");
LOGGER.log(Level.INFO, "Init class URL: " + org.apache.xml.security.Init.class.getProtectionDomain().getCodeSource().getLocation());
LOGGER.log(Level.INFO, cfile1);
В новых версиях КриптоПро JCP (JCSP) инициализацию выполнит одна строчка:
ru.CryptoPro.JCPxml.xmldsig.JCPXMLDSigInit.init();
Теперь нужно Apache Santuario научить новым правилам трансформации, которые диктует СМЭВ 3. Для этого регистрируем класс трансформации:
try {
Transform.register(SmevTransformSpi.ALGORITHM_URN, SmevTransformSpi.class.getName());
santuarioIgnoreLineBreaks(true);
LOGGER.log(Level.INFO, "SmevTransformSpi has been initialized");
} catch (AlgorithmAlreadyRegisteredException e) {
LOGGER.log(Level.INFO, "SmevTransformSpi Algorithm already registered: " + e.getMessage());
}
Заодно сразу выполняем требование из Методических указаний:
Требования к форматированию В XML-структуре подписи между элементами не допускается наличие текстовых узлов, в том числе переводов строки.
santuarioIgnoreLineBreaks(true);
private static final String IGNORE_LINE_BREAKS_FIELD = "ignoreLineBreaks";
/**
* Apache Santuario privileged switch IgnoreLineBreaks property
*
* @param mode
*/
private void santuarioIgnoreLineBreaks(Boolean mode) {
try {
Boolean currMode = mode;
AccessController.doPrivileged(new PrivilegedExceptionAction<Boolean>() {
public Boolean run() throws Exception {
Field f = XMLUtils.class.getDeclaredField(IGNORE_LINE_BREAKS_FIELD);
f.setAccessible(true);
f.set(null, currMode);
return false;
}
});
} catch (Exception e) {
LOGGER.warning("santuarioIgnoreLineBreaks " + ExceptionUtils.getFullStackTrace(e));
}
}
Делается это в привилегированном блоке AccessController.doPrivileged
и через reflection, из-за особенности реализации свойства ignoreLineBreaks в Santuario.
Просто через настройку системного свойства:
System.setProperty("org.apache.xml.security.ignoreLineBreaks", "true");
не работает.
Через настройку опции JVM:
-Dcom.sun.org.apache.xml.internal.security.ignoreLineBreaks=true
работает.
Если взглянуть на код класса org.apache.xml.security.utils.XMLUtils, то можно увидеть, что поле ignoreLineBreaks статическое, инициализируется в привилегированном блоке из системного свойства «org.apache.xml.security.ignoreLineBreaks».
private static boolean ignoreLineBreaks =
AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
public Boolean run() {
return Boolean.valueOf(Boolean.getBoolean
("org.apache.xml.security.ignoreLineBreaks"));
}
}).booleanValue();
public static boolean ignoreLineBreaks() {
return ignoreLineBreaks;
}
Такая реализация приводит к невозможности гибко настроить в одном Java процессе для части методов игнорировать перевод строк, а для другой части не игнорировать.
Т.е., если одно приложение выполняет подписи XMLDsig, СМЭВ 2 и СМЭВ 3, все XML документы, обработанные Santuario должны на выходе лишиться перевода строк.
С этим свойством, конечно, возникает вопрос к Apache Santuario:
Подпись сообщений СМЭВ 3
Для подписи документов СМЭВ 3 все готово.
Код подписания выглядит следующим образом:
private static final String XMLDSIG_MORE_GOSTR34102001_GOSTR3411 = "http://www.w3.org/2001/04/xmldsig-more#gostr34102001-gostr3411";
private static final String XMLDSIG_MORE_GOSTR3411 = "http://www.w3.org/2001/04/xmldsig-more#gostr3411";
private static final String CANONICALIZATION_METHOD = "http://www.w3.org/2001/10/xml-exc-c14n#";
private static final String DS_SIGNATURE = "//ds:Signature";
private static final String SIG_ID = "sigID";
private static final String COULD_NOT_FIND_XML_ELEMENT_NAME = "ERROR! Could not find xmlElementName = ";
private static final String GRID = "#";
private static final String XML_SIGNATURE_ERROR = "xmlDSignature ERROR: ";
try {
// инициализация объекта чтения XML-документа
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
// установка флага, определяющего игнорирование пробелов в
// содержимом элементов при обработке XML-документа
dbf.setIgnoringElementContentWhitespace(true);
// установка флага, определяющего преобразование узлов CDATA в
// текстовые узлы при обработке XML-документа
dbf.setCoalescing(true);
// установка флага, определяющего поддержку пространств имен при
// обработке XML-документа
dbf.setNamespaceAware(true);
// загрузка содержимого подписываемого документа на основе
// установленных флагами правил из массива байтов data DocumentBuilder documentBuilder = dbf.newDocumentBuilder();
Document doc = documentBuilder.parse(new ByteArrayInputStream(data));
/*
* Добавление узла подписи <ds:Signature> в загруженный XML-документ
*/
// алгоритм подписи (ГОСТ Р 34.10-2001)
final String signMethod = XMLDSIG_MORE_GOSTR34102001_GOSTR3411;
// алгоритм хеширования, используемый при подписи (ГОСТ Р 34.11-94)
final String digestMethod = XMLDSIG_MORE_GOSTR3411;
final String canonicalizationMethod = CANONICALIZATION_METHOD;
String[][] filters = {{XPath2FilterContainer.SUBTRACT, DS_SIGNATURE}};
String sigId = SIG_ID;
// инициализация объекта формирования ЭЦП в соответствии с
// алгоритмом ГОСТ Р 34.10-2001
XMLSignature sig = new XMLSignature(doc, "", signMethod, canonicalizationMethod);
// определение идентификатора первого узла подписи
sig.setId(sigId);
// получение корневого узла XML-документа
Element anElement = null;
if (xmlElementName == null) {
anElement = doc.getDocumentElement();
} else {
NodeList nodeList = doc.getElementsByTagName(xmlElementName);
anElement = (Element) nodeList.item(0);
}
// = doc.getElementById("#AppData");
// добавление в корневой узел XML-документа узла подписи
if (anElement != null) {
anElement.appendChild(sig.getElement());
} else {
throw new SignatureProcessorException(COULD_NOT_FIND_XML_ELEMENT_NAME + xmlElementName);
}
/*
* Определение правил работы с XML-документом и добавление в узел подписи этих
* правил
*/
// создание узла преобразований <ds:Transforms> обрабатываемого
// XML-документа
Transforms transforms = new Transforms(doc);
// добавление в узел преобразований правил работы с документом
// transforms.addTransform(Transforms.TRANSFORM_ENVELOPED_SIGNATURE);
transforms.addTransform(Transforms.TRANSFORM_C14N_EXCL_OMIT_COMMENTS);
transforms.addTransform(SmevTransformSpi.ALGORITHM_URN);
// добавление в узел подписи ссылок (узла <ds:Reference>),
// определяющих правила работы с
// XML-документом (обрабатывается текущий документ с заданными в
// узле <ds:Transforms> правилами
// и заданным алгоритмом хеширования)
sig.addDocument(xmlElementID == null ? "" : GRID + xmlElementID, transforms, digestMethod);
/*
* Создание подписи всего содержимого XML-документа на основе закрытого ключа,
* заданных правил и алгоритмов
*/
// создание внутри узла подписи узла <ds:KeyInfo> информации об
// открытом ключе на основе
// сертификата
sig.addKeyInfo(x509Cert);
// создание подписи XML-документа
sig.sign(privateKey);
// определение потока, в который осуществляется запись подписанного
// XML-документа
bais = new ByteArrayOutputStream();
// инициализация объекта копирования содержимого XML-документа в
// поток
TransformerFactory tf = TransformerFactory.newInstance();
// создание объекта копирования содержимого XML-документа в поток
Transformer trans = tf.newTransformer();
// копирование содержимого XML-документа в поток
trans.transform(new DOMSource(doc), new StreamResult(bais));
bais.close();
} catch (TransformationException e) {
throw new SignatureProcessorException("TransformationException " + XML_SIGNATURE_ERROR + e.getMessage());
} catch (XMLSignatureException e) {
throw new SignatureProcessorException("XMLSignatureException " + XML_SIGNATURE_ERROR + e.getMessage());
} catch (TransformerException e) {
throw new SignatureProcessorException("TransformerException " + XML_SIGNATURE_ERROR + e.getMessage());
} catch (IOException e) {
throw new SignatureProcessorException("IOException " + XML_SIGNATURE_ERROR + e.getMessage());
} catch (XMLSecurityException e) {
throw new SignatureProcessorException("XMLSecurityException " + XML_SIGNATURE_ERROR + e.getMessage());
} catch (SAXException e) {
throw new SignatureProcessorException("SAXException " + XML_SIGNATURE_ERROR + e.getMessage());
} catch (ParserConfigurationException e) {
throw new SignatureProcessorException(
"ParserConfigurationException " + XML_SIGNATURE_ERROR + e.getMessage());
}
return bais.toByteArray();
Основными параметрами здесь являются:
byte[] data, // XML сообщение в виде массива байтов
String xmlElementName, // имя элемента в XML вместе с префиксом, в который следует добавить подпись, для СМЭВ-3 в общем случае "ns2:CallerInformationSystemSignature"
String xmlElementID // ID элемента в XML (если присутствует) вместе с префиксом, на который следует поставить подпись, для СМЭВ-3 в общем случае "SIGNED_BY_CONSUMER"
X509Certificate certificate // сертификат открытого ключа проверки подписи
PrivateKey privateKey // закрытый ключ подписи
Проверка подписи сообщения СМЭВ 3
Код проверки подписи выглядит следующим образом:
private static final QName QNAME_SIGNATURE = new QName("http://www.w3.org/2000/09/xmldsig#", "Signature", "ds");
private static final String SIGNATURE_NOT_FOUND = "Signature not found!";
private static final String SIGNATURE_NOT_VALID = "Signature not valid";
private static final String SMEV_SIGNATURE_PASSED_CORE_VALIDATION = "SmevSignature passed core validation";
private static final String VERIFY_SIGNATURE_ON_XML_IO_EXCEPTION = "Verify signature on XML IOException: ";
private static final String VERIFY_SIGNATURE_ON_XML_PARSER_CONFIGURATION_EXCEPTION = "Verify signature on XML ParserConfigurationException: ";
private static final String VERIFY_SIGNATURE_ON_XML_SAX_EXCEPTION = "Verify signature on XML SAXException: ";
private static final String VERIFY_SIGNATURE_ON_XML_XML_SIGNATURE_EXCEPTION = "Verify signature on XML XMLSignatureException: ";
private static final String VERIFY_SIGNATURE_ON_XML_XML_SECURITY_EXCEPTION = "Verify signature on XML XMLSecurityException: ";
private static final String ID = "Id";
boolean coreValidity = true;
try {
DocumentBuilderFactory bf = DocumentBuilderFactory.newInstance();
bf.setNamespaceAware(true);
DocumentBuilder b = bf.newDocumentBuilder();
Document doc = b.parse(new InputSource(new ByteArrayInputStream(signedXmlData)));
NodeList sigs = doc.getElementsByTagNameNS(QNAME_SIGNATURE.getNamespaceURI(), QNAME_SIGNATURE.getLocalPart());
org.apache.xml.security.signature.XMLSignature sig = null;
sigSearch: {
for (int i = 0; i < sigs.getLength(); i++) {
Element sigElement = (Element) sigs.item(i);
String sigId = sigElement.getAttribute(ID);
if (sigId != null) {
sig = new org.apache.xml.security.signature.XMLSignature(sigElement, "");
break sigSearch;
}
}
throw new XMLSignatureVerificationException(SIGNATURE_NOT_FOUND);
}
org.apache.xml.security.keys.KeyInfo ki = (org.apache.xml.security.keys.KeyInfo) sig.getKeyInfo();
X509Certificate certificate = ki.getX509Certificate();
if (!sig.checkSignatureValue(certificate.getPublicKey())) {
coreValidity = false;
LOGGER.log(Level.INFO, SIGNATURE_NOT_VALID);
} else {
LOGGER.log(Level.INFO, String.format(SMEV_SIGNATURE_PASSED_CORE_VALIDATION));
}
} catch (IOException e) {
throw new XMLSignatureVerificationException(VERIFY_SIGNATURE_ON_XML_IO_EXCEPTION + ExceptionUtils.getStackTrace(e));
} catch (ParserConfigurationException e) {
throw new XMLSignatureVerificationException(VERIFY_SIGNATURE_ON_XML_PARSER_CONFIGURATION_EXCEPTION + ExceptionUtils.getStackTrace(e));
} catch (SAXException e) {
throw new XMLSignatureVerificationException(VERIFY_SIGNATURE_ON_XML_SAX_EXCEPTION + ExceptionUtils.getStackTrace(e));
} catch (org.apache.xml.security.signature.XMLSignatureException e) {
throw new XMLSignatureVerificationException(VERIFY_SIGNATURE_ON_XML_XML_SIGNATURE_EXCEPTION + ExceptionUtils.getStackTrace(e));
} catch (XMLSecurityException e) {
throw new XMLSignatureVerificationException(VERIFY_SIGNATURE_ON_XML_XML_SECURITY_EXCEPTION + ExceptionUtils.getStackTrace(e));
}
return coreValidity;
Проблемы. Хэш не совпадает
Внимание!
Для отладки использовался пример конверта СМЭВ 3 SendRequestRequestNoAttach.xml
Из него был удален элемент ds:Signature с целью подписать сообщение заново и сверить с оригиналом.
Несмотря на то, что метод подписи и трансформация SmevTransformSpi, взятая из Методических указаний, отрабатывали, на выходе был подписанный документ, подпись которого при онлайн-проверке на портале СМЭВ 3 трактовалась как
ЭП-ОВ не подтверждена: Ошибка проверки ЭП: Нарушена целостность ЭП
Почему
<ds:DigestValue>e76oVeYGapFDE+PV6glsj0XDjLHydLMd0cSkFPY8fWk=</ds:DigestValue>
не совпадал с оригинальным примером:
<ds:DigestValue>/jXl70XwnttJB5sSokwh8SaVHwo2gjgILSu0qBaLUAo==</ds:DigestValue>
Для диагностики причин в класс SmevTransformSpi в метод process был добавлен свой XMLEventWriter.
ByteArrayOutputStream baos = new ByteArrayOutputStream();
XMLEventWriter bdst =
outputFactory.get().createXMLEventWriter(baos, ENCODING_UTF_8);
для параллельного анализа всех этапов трансформации.
Нормализованный элемент XML, на который требуется поставить подпись, выглядел следующим образом:
<ns1:SenderProvidedRequestData xmlns:ns1="urn://x-artefacts-smev-gov-ru/services/message-exchange/types/1.1" Id="SIGNED_BY_CONSUMER"><ns1:MessageID>db0486d0-3c08-11e5-95e2-d4c9eff07b77</ns1:MessageID><ns2:MessagePrimaryContent xmlns:ns2="urn://x-artefacts-smev-gov-ru/services/message-exchange/types/basic/1.1"><ns3:BreachRequest xmlns:ns3="urn://x-artefacts-gibdd-gov-ru/breach/root/1.0" Id="PERSONAL_SIGNATURE"><ns3:RequestedInformation><ns4:RegPointNum xmlns:ns4="urn://x-artefacts-gibdd-gov-ru/breach/commons/1.0">Т785ЕС57</ns4:RegPointNum></ns3:RequestedInformation><ns3:Governance><ns4:Name>ГИБДД РФ</ns4:Name><ns4:Code>GIBDD</ns4:Code><ns4:OfficialPerson><ns5:FamilyName xmlns:ns5="urn://x-artefacts-smev-gov-ru/supplementary/commons/1.0.1">Загурский</ns5:FamilyName><ns5:FirstName>Андрей</ns5:FirstName><ns5:Patronymic>Петрович</ns5:Patronymic></ns4:OfficialPerson></ns3:Governance></ns3:BreachRequest></ns2:MessagePrimaryContent><ns1:TestMessage></ns1:TestMessage></ns1:SenderProvidedRequestData>
Поиск решения показал, что, во-первых форум КриптоПро, нормализованный документ может выглядеть на самом деле иначе и соответственно его хэш будет другой и возможно правильный.
Во-вторых, привел в GitHub, где был выложен класс SmevTransformSpi более старой версии.
Старая версия класса трансформации выдала следующий нормализованный документ:
<ns1:SenderProvidedRequestData xmlns:ns1="urn://x-artefacts-smev-gov-ru/services/message-exchange/types/1.1" Id="SIGNED_BY_CONSUMER"><ns1:MessageID>db0486d0-3c08-11e5-95e2-d4c9eff07b77</ns1:MessageID><ns2:MessagePrimaryContent xmlns:ns2="urn://x-artefacts-smev-gov-ru/services/message-exchange/types/basic/1.1"><ns3:BreachRequest xmlns:ns3="urn://x-artefacts-gibdd-gov-ru/breach/root/1.0" Id="PERSONAL_SIGNATURE"><ns3:RequestedInformation><ns4:RegPointNum xmlns:ns4="urn://x-artefacts-gibdd-gov-ru/breach/commons/1.0">Т785ЕС57</ns4:RegPointNum></ns3:RequestedInformation><ns3:Governance><ns5:Name xmlns:ns5="urn://x-artefacts-gibdd-gov-ru/breach/commons/1.0">ГИБДД РФ</ns5:Name><ns6:Code xmlns:ns6="urn://x-artefacts-gibdd-gov-ru/breach/commons/1.0">GIBDD</ns6:Code><ns7:OfficialPerson xmlns:ns7="urn://x-artefacts-gibdd-gov-ru/breach/commons/1.0"><ns8:FamilyName xmlns:ns8="urn://x-artefacts-smev-gov-ru/supplementary/commons/1.0.1">Загурский</ns8:FamilyName><ns9:FirstName xmlns:ns9="urn://x-artefacts-smev-gov-ru/supplementary/commons/1.0.1">Андрей</ns9:FirstName><ns10:Patronymic xmlns:ns10="urn://x-artefacts-smev-gov-ru/supplementary/commons/1.0.1">Петрович</ns10:Patronymic></ns7:OfficialPerson></ns3:Governance></ns3:BreachRequest></ns2:MessagePrimaryContent><ns1:TestMessage></ns1:TestMessage></ns1:SenderProvidedRequestData>
С ним хэш стал совпадать, а подпись успешно проходить валидацию.
Сравнение версий класса SmevTransformSpi показала, что помимо добавленных в новой реализации дополнительных функций логирования и диагностики в debug режиме:
if (logger.isDebugEnabled()) {
debugStream = new DebugOutputStream(argDst);
dst = outputFactory.get().createXMLEventWriter(debugStream, ENCODING_UTF_8);
} else {
dst = outputFactory.get().createXMLEventWriter(argDst, ENCODING_UTF_8);
}
Класс из Методических указаний не содержит нужную строчку, или содержит опечатку:
Отсутствует строка:
prefixMappingStack.pop();
, которая удаляет первый объект из стека с префиксами
Stack<List<Namespace>> prefixMappingStack = new Stack<List<Namespace>>();
, что приводило к неверной работе SmevTransformSpi.
Добавление этой строки в новую версию SmevTransformSpi.java решило проблему.
Работающий класс трансформации и конверт с подписью можно посмотреть в github.com/VBurmistrov/Smev3
Результаты
Подписание конвертов СМЭВ 3 выполняется успешно.
Сообщения проходят проверку на портале Электронного правительства Госуслуги
И в собственном приложении:
Из нашей статьи вы узнаете:
В работе электронной подписи периодически возникают различные ошибки. Иногда они являются результатом неправильных действий пользователя, а иногда — это последствие технических неполадок.
Основные проблемы в работе ЭЦП
Мы выделили самые часто встречающиеся ошибки в работе КЭП. Ниже мы будем описывать причину проблемы и путь её решения.
Выбранная подпись не авторизована
Такая проблема появляется, когда используется новая КЭП на ЭТП (электронной торговой площадке), если пользователь не был зарегистрирован. То же самое происходит, когда не был зарегистрирован сам сертификат.
Решением данной проблемы является авторизация:
- Перейдите на главную страницу торговой площадки, а затем → «Вход по ЭЦП».
- Выберите «Авторизация ЭЦП» и нажмите кнопку «Пользователь организации».
- Подтвердите выбор нового ключа ЭЦП.
- В появившемся окне «Идентификационные данные» заполните все обязательные поля и нажмите «Отправить на рассмотрение».
В течение часа подпись будет зарегистрирована и ошибка исчезнет. Если же она всё-таки повторятся, то отключите антивирус или поставьте электронную торговую площадку в исключения.
ЭЦП проставлено сертификатом, на который нет заключённого соглашения
Такая проблема появляется при обращении в ПФР без заключённого с ними соглашения.
Чтобы решить проблему, нужно заключить договор с ПФР в письменном виде. Если же он уже был заключён, нужно проверить соответствие данных в документе с данными в сертификате электронной подписи.
Алгоритм ключа сертификата не поддерживается
Название ошибки говорит само за себя — тут либо программное обеспечение несовместимо, либо неправильно установлена КриптоПро CSP.
В первую очередь нужно проверить компьютер на совместимость с программными средствами. Если здесь всё нормально, то попробуйте переустановить КриптоПро CSP. Также проверьте хранилище сертификатов на наличие там закрытого ключа. В крайнем случае понадобится переустановка операционной системы.
Электронная подпись документа невалидна
Такая ошибка появляется при работе в системах «1С» как следствие того, что на устройстве не установлен корневой сертификат УЦ. Он нужен для подтверждения того, что удостоверяющий центр сертифицирован Минцифры.
Исправить ошибку можно путём установки соответствующего сертификата в правильное хранилище → «Доверенные корневые центры сертификации». Найти его можно на сайте удостоверяющего центра.
Невозможно создание объекта сервером программирования объектов ЭЦП
Подобная проблема может проявиться при подписании электронных документов и при создании запросов в информационных системах.
Чтобы исправить ошибку, достаточно переустановить КриптоПро CSP и КриптоПро ЭЦП Browser plug-in. Если ошибка сохраняется, то скачайте и установите capicom.dll. В крайнем случае отключите защитник Windows и центр обеспечения безопасности.
Ваш сертификат ключа подписи включён в список отозванных
Такая ошибка появляется, когда истекает срок действия сертификата. Решением является продление срока действия.
Если же ошибка возникает, а срок сертификата ещё не подошёл к концу, то нужно установить СОС (список отозванных сертификатов) и перезагрузить компьютер. Если это не помогло, свяжитесь с удостоверяющим центром.
Техническая поддержка продуктов «Астрал-ЭТ» и «1С-ЭТП» работает круглосуточно и поможет решить любую возникшую проблему.
У применения ЭЦП довольно много нюансов, которые в некоторых случаях требуют внимания к себе. Чтобы разобраться в них, мы подготовили материал, в котором вы найдёте ответы на основные вопросы, касающиеся использования ЭЦП.
Получение выписки ЕГРН с помощью электронной подписи
Вопрос получения такого свидетельства актуален при совершении любой сделки с недвижимостью. Заказать выписку можно на бумаге, либо в электронном формате.
Рассказываем, как получить электронную выписку с помощью ЭЦП и сколько это будет стоить.
Как получить выписку из ЕГРЮЛ с ЭЦП ФНС
Выписка из Единого государственного реестра юридических лиц содержит все основные сведения о юрлице. Она необходима для того, чтобы удостовериться или подтвердить данные государственной регистрации, уточнить сведения об адресе местонахождения юрлица и др. Выписку в электронном виде можно получить с помощью электронной подписи. Как это сделать? Отвечаем на этот вопрос в нашей статье.
Как оформить заявление на получение ЭЦП
Согласно правилам оформления ЭП, для получения электронной подписи необходимо подготовить пакет документов и подать заявление в удостоверяющий центр или МФЦ (в зависимости от вида подписи). В статье мы подробно рассмотрим все вопросы оформления электронной подписи: какие документы нужны, в каком порядке происходит получение сертификата и куда нужно обращаться.
Как выглядит электронная подпись
Увидеть ЭЦП в электронном документе своими глазами в буквальном смысле, конечно, нельзя, потому что это не просто какой-то графический символ. Однако можно, например, проверить документ, чтобы наглядно убедиться, что он подписан с помощью электронной подписи. В статье мы раскроем все основные вопросы, касающиеся подписания документов электронной подписью, а также выясним, какие средства и реквизиты для этого применяются.
Как зарегистрироваться в ЕИС
Единая информационная система в сфере закупок (ЕИС) создана для формирования, обработки и хранения данных о закупках. Это позволяет в значительной мере упростить доступ к сведениям о торгах. Рассказываем, что нужно для регистрации в ЕИС и в каком порядке проходит регистрация.
Как работает ЭП
Применение ЭЦП обеспечивает сохранность данных и неизменность подписанного документа, а также позволяет идентифицировать подписанта. Как же работает электронная подпись? Чтобы ответить на этот вопрос, нужно сначала разобраться как устроена подпись и какие средства шифрования используются для её применения. Об этом и пойдёт речь далее.
Как сделать КЭП для торгов
Для участия в торгах необходима квалифицированная электронная подпись. Она потребуется на всех этапах — от регистрации на электронной торговой площадке до подписания договора с контрагентом. Чтобы оформить квалифицированную ЭЦП для торгов, необходимо подать заявление в аккредитованный удостоверяющий центр. Детальное описание процедуры выпуска КЭП — в нашей статье.
Что такое корневой сертификат ЭЦП
В корневом сертификате содержатся сведения об удостоверяющем центре. Без него работа с электронной подписью невозможна. Где достать корневой сертификат? Как установить? Ответы на эти вопросы — в нашей статье.
Продление сертификата ЭП
Сертификаты электронной подписи имеют срок годности, по истечении которого нужно обращаться в удостоверяющий центр для продления. Рассказываем, как узнать срок действия сертификата и в каком порядке подаётся заявление на его продление.
Что такое сертификат ключа электронной подписи
В сертификате ключа ЭЦП содержатся сведения о владельце электронной подписи. В ЭДО сертификат ключа служит подтверждением того, что подтверждением того, что электронная подпись действительно принадлежит её владельцу. Информация о составе сертификата ключа и о том, какие учреждения занимаются выпуском сертификатов — в нашей статье.
Создание заявления на получение ЭП
Чтобы оформить на себя электронную подпись электронную подпись, необходимо подать специальное заявление в аккредитованный удостоверяющий центр. Мы подготовили пошаговые инструкции для юридических лиц, индивидуальных предпринимателей, а также физических лиц. С их помощью вы сможете без труда оформить заявку на получение ЭЦП в личном кабинете пользователя сервиса «Астрал-ЭТ».
Срок действия ключа электронной подписи
Максимальный срок, на который выдаётся сертификат ключа ЭП, составляет 12 месяцев. Чтобы продлить действие сертификата, владелец электронной подписи должен за 14 дней до истечения срока подать заявку на продление действия сертификата. В противном случае работа сертификата будет приостановлена, как только срок его действия истечёт. Подробнее в нашей статье.
Структура ЭЦП: из чего состоит электронная подпись
В состав электронной подписи входят ключевая пара (она состоит из ключей: открытого и закрытого), а также сертификат проверки ключей. Подробности — в нашей статье.
Что делать, если ЭЦП украли
Кража ЭП — это, безусловно, вопрос, требующий немедленного решения. Как узнать, что электронную подпись украли? Что делать в этом случае? Как предупредить возможную кражу или утерю электронной подписи? Рассказываем в нашей специальной статье.
Что такое сертификат ЭП
Для чего нужен сертификат электронной подписи? Что он представляет из себя и какие данные содержит? Рассказываем в нашей статье.
Что такое ЭЦП
Электронная подпись — это атрибут документа, составленного в электронном виде. В зависимости от своего вида ЭЦП может быть равноценной рукописной подписи, а также обеспечивать документы юридической значимостью. Подробнее в нашей статье.
Что такое штамп времени в ЭП
В момент подписания электронного документа с помощью ЭЦП формируется атрибут, который называется штамп времени. Он содержит информацию о дате и времени подписании документа. При подписании документа программа для работы с ЭЦП обращается к службе TSA (time stamping authority), которая сообщает точные дату и время, после чего формируется штамп. Рассказываем об этом здесь.
Как продлить ЭП для ЕГАИС
Для работы с ЕГАИС нужна КЭП. Поскольку срок действия любой электронной подписи ограничен, возникает закономерный вопрос: как продлить её действие? Рассказываем.
Токены ЭЦП. Обзор основных разновидностей токенов в России
Токенами называют USB-носители, предназначенные для хранения и применения ключа электронной подписи. В России сертифицировано несколько разновидностей токенов. В статье мы рассмотрим наиболее распространённые варианты ключевых носителей и расскажем, по какому принципу их выбирать.
Форум КриптоПро
»
Средства криптографической защиты информации
»
КриптоПро .NET
»
Ошибка ЭП-ОВ не соответствует подписанным данным: Нарушена целостность ЭП
JohnN86 |
|
Статус: Новичок Группы: Участники
|
Отправляю запрос в СМЭВ3 <soap:Envelope xmlns:wsse=»http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd» Получаю ответ: <?xml version=»1.0″ encoding=»UTF-8″ ?> |
|
|
two_oceans |
|
Статус: Эксперт Группы: Участники Сказал(а) «Спасибо»: 110 раз |
Автор: JohnN86 Отправляю запрос в СМЭВ3 …. Получаю ответ:… Добрый день. 1) в soap:Header подпись лишняя (нужна была в смэв 2), в смэв 3 soap:Header пуст; 2) CallerInformationSystemSignature — Signature — SignedInfo — Reference — Transforms должен содержать трансформ СМЭВ3 urn://smev-gov-ru/xmldsig/transform после эксклюзивной каноникализации http://www.w3.org/2001/10/xml-exc-c14n# Поясню почему это нужно: приведенный Вами документ содержит форматирование переводами строк и отступы перед тегами (пробелами или табуляцией) — в реальном запросе эти символы и отступы не нужны, но при этом их обработка не особо четко регламентирована стандартами — применить стандарты не в том порядке и результат другой. Трансформ СМЭВ как раз среди прочих возможных несоответствий удаляет переводы строк и табуляцию: нет символа — нет проблемы. 3) Рекомендуется изначально удалить в документе все отступы и переводы строк перед подписанием. Ну зачем Вам нужен отступ перед значением в теге SignatureValue. На форум прикреплять тоже без дополнительного форматирования, копированием из Блокнота (любой браузер умеет отобразить XML без переводов строк в читаемом виде). Спецификация СМЭВ 3 особо подчеркивает что все содержимое SignedInfo должно быть в одну строку. 4) форум искажает документы вставленные в сам текст сообщения, а сам вид страницы форума перекашивается. «Вместо тысячи слов» пример ответа СМЭВ с двумя подписями (по которому я калибрую свою программу) и одновременно пример как прикреплять на форум: UPDATE: После очистки документа из предыдущего сообщения (пункты 1 и 3) от отступов и переводов строк, обнуления soap:Header, вышло что подпись «внезапно» верна. Тем не менее без нужного трансформа СМЭВ ее скорее всего не примет. Тестовая страница не приняла. Код:
Отредактировано пользователем 27 ноября 2020 г. 13:53:03(UTC) |
|
|
1 пользователь поблагодарил two_oceans за этот пост. |
Андрей *
оставлено 27.11.2020(UTC) |
Пользователи, просматривающие эту тему |
Guest |
Форум КриптоПро
»
Средства криптографической защиты информации
»
КриптоПро .NET
»
Ошибка ЭП-ОВ не соответствует подписанным данным: Нарушена целостность ЭП
Быстрый переход
Вы не можете создавать новые темы в этом форуме.
Вы не можете отвечать в этом форуме.
Вы не можете удалять Ваши сообщения в этом форуме.
Вы не можете редактировать Ваши сообщения в этом форуме.
Вы не можете создавать опросы в этом форуме.
Вы не можете голосовать в этом форуме.