Смэв 3 0

Правительство Свердловской областиОфициальный сайтМногофункциональный центрОфициальный сайт ГБУ СО «МФЦ»Единый портал государственных и муниципальных услуг (функций)Единый портал государственных и муниципальных услуг (функций) Российской ФедерацииГод памяти и славыГод2020.рф — официальный сайт Года памяти и славы. Ресурс содержит информацию об основных акциях и мероприятиях, проводимых в рамках Года памяти и славы по всей России Общероссийское голосование Общероссийское голосование 9 мая Победа в Великой Отечественной войне – героический подвиг народа. День Победы мы отмечаем как главный праздник страны. Вечная память павшим в боях! Слава победителям! Развитие электронного правительства Направления развития электронного правительства Свердловской области Ваш контроль Ваш контроль Социальная поддержка инвалидов Раздел посвященный вопросам формирования доступной среды жизнедеятельности и предоставления услуг для инвалидов ЭИОК Свердловской области Безопасность населения и территорий в чрезвычайных ситуациях, эффективность ликвидации чрезвычайных ситуаций напрямую зависит как от качества и уровня подготовки должностных лиц и специалистов ГО и РСЧС, так и от уровня подготовленности населения в целом. Сетевичок.рф Национальный рейтинг «Страна молодых» Опрос: Удовлетворенность качеством товаров и услуг и конкуренцией на территории Свердловской области Опрос: Удовлетворенность качеством товаров и услуг и конкуренцией на территории Свердловской области Инвестиционный портал Свердловской области Инвестиционный портал Свердловской области У меня есть проект Прием заявок на сопровождение инвестиционных проектов осуществляется посредством Инвестиционного портала Свердловской области через кнопку «У меня есть проект» Оператор электронного правительства О функциях и задачах государственного бюджетного учреждения «Оператор электронного правительства» Защита прав потребителей Свердловской области Сайт содержит базу данных результатов проведенных проверок, на предмет нарушения прав потребителя, а также обеспечивает возможность оперативного поиска необходимой информации по заданным параметрам (по объектам, организациям, производителям). Бесплатная юридическая помощь Бесплатная юридическая помощь Исполнение Указов Президента Российской Федерации от 7 мая 2012 года Указы Президента Российской Федерации от 7 мая 2012 года Портал «Открытое Правительство Свердловской области» Портал «Открытое Правительство» Свердловской области принципиально новая платформой социального партнерства граждан и органов государственной власти Пилотным органом власти для проекта выступает министерство транспорта и связи Свердловской области. Портал «Работа в России» Поиск вакансий и соискателей работы, а также рабочих мест для инвалидов и вакансий на общественные и временные работы. Аналитические материалы. Приложение «Качество связи» Приложение «Качество связи» для Android — это проект, предназначенный для автоматизированного сбора данных о качестве связи на территории РФ. Установив приложение, вы получаете возможность самостоятельно собирать данные о мощности сигнала сети сотовой связи, в тех местах где вы находитесь. Нормативные правовые акты в Российской Федерации Нормативные правовые акты в Российской Федерации Доступная среда Карта доступности социальных объектов интернет–портала «Жить вместе» государственной программы Российской Федерации «Доступная среда»

В материале представлен алгоритм поиска видов сведений СМЭВ 3. Рассматриваются источники информации о ВС: интерфейс Технологического портала СМЭВ, План перехода на использование Методических рекомендаций 3.х, Единый отчет СМЭВ. Описывается процесс проверки работоспособности продуктивной версии ВС.

Проблема поиска вида сведений в СМЭВ

Разработчики СМЭВ в качестве основного инструмента поиска видов сведений СМЭВ 3 предлагают использовать веб-интерфейс, расположенный на Технологическом портале по адресу https://smev3.gosuslugi.ru. При этом пользователю предоставляется возможность поиска только по названию вида сведений, в то время как для предыдущей версии Техпортала был предусмотрен гораздо более широкий набор фильтров:

  • по владельцу сервиса (ведомству или организации)
  • по идентификатору
  • по ключевому слову в описании
  • по области применения
  • по доступности (общедоступный/ограниченно доступный)

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

  • не все сервисы СМЭВ2 переводятся в СМЭВ3
  • при переходе со СМЭВ2 на СМЭВ3 поставщик может существенно изменить название сервиса (вида сведений), разбить один сервис на несколько ВС, или, наоборот, объединить сервисы (например, сервис СМЭВ2 ГИС ГМП в настоящий момент разбит на 10 видов сведений)
  • между выводом вида сведений в тестовую и продуктивную среду может пройти очень много времени (до 6 месяцев и более)
  • очень часто в тестовую и продуктивную среду выводят несколько версий одного и того же вида сведений
  • на Техпортале СМЭВ перестали публиковать актуальные данные о потребителях ВС
  • карточки видов сведений на Техпортале СМЭВ не индексируются поисковыми системами
  • наконец, в последнее время, в связи с необходимостью формального соблюдения плановых сроков, часто встречается практика установки «заглушек» на виды сведений в продуктивной среде (ВС выведен в продуктив, но либо не отвечает на продуктивные запросы, либо отвечает тестовыми данными)

Указанные проблемы усложняют поиск информации о виде сведений, а также затрудняю принятие решения о старте работ по подключению к ВС.

Далее в статье будут рассмотрены альтернативные источники информации о работе видов сведений, а также представлен оптимальный алгоритм поиска вида сведений.

Дополнительные источники данных о видах сведений

План перехода на предоставление сведений с использованием единого электронного сервиса СМЭВ

На Технологическом портале СМЭВ опубликован документ «Приложение 2 к протоколу Плану перехода…», в котором представлен перечень ВС и сроки перевода электронных сервисов на исполнение Методических рекомендаций по работе с ЕСМЭВ версии 3. Этот документ является очень ценным по нескольким причинам.

Во-первых, в нем содержится однозначное соответствие между сервисами СМЭВ2 и видами сведений СМЭВ3.

Во-вторых, все сервисы и виды сведений сгруппированы по ведомствам (поставщикам).

В-третьих, в документе представлены даты вывода видов сведений в тестовую и продуктивную среду. Стоит, однако, учитывать, что данные сроки являются ориентировочными и могут сдвигаться. Формальный вывод вида сведений в продуктив также не свидетельствует о его работоспособности.

Самое главное — документ представляет собой файл в формате excel. В нем работает стандартный функционал поиска. То есть, можно поводить поиск по ведомству, названию сервиса СМЭВ 2 и вида сведений СМЭВ 3.

Минус документа заключается в том, что в нем содержится далеко не полный список видов сведений, а лишь те ВС, которым соответствуют сервисы СМЭВ2.

Единый отчет по СМЭВ

В Ситуационном центре электронного правительства публикуется документ «Единый отчет по СМЭВ». Доступ к нему предоставляется пользователям с учетной записью органа власти. Путь к документу: «Опубликованные отчеты» => «СМЭВ» => «Единый отчет по СМЭВ» => «СМЭВ. Единый отчет по СМЭВ: Отчёт №6_СМЭВ_Единый отчет по СМЭВ_». Отчет публикуется ежемесячно.

Документ представляет собой файл формата excel и содержит очень много полезной статистической информации. Среди прочего в нем есть вкладка «Невостребованные сервисы», на которой перечислены сервисы и виды сведений, к которым не поступают запросы. Таким образом, если вид сведений должен предоставлять востребованную информацию (1), уже выведен в продуктивную среду (2) и при этом включен в число «невостребованных» (3) — скорее всего, фактически он не работоспособен.

Пример отчета номер 6 «Единый отчет по СМЭВ».

Файл «Статус ВС»

Недавно на главной страницы Технологического портала СМЭВ 3 появился информационный блок со ссылкой на сводный файл в формате excel с информацией о степени готовности всех видов сведений. Файл находится в открытом доступе. Найти его можно на главной странице техпортала: нужно открыть стандартный функционал поиска по содержимому страницы и найти фразу «отчет по статусу регистрации видов сведений». Под найденным текстом будет ссылка на актуальный вариант файла.

Пример файла «Статус ВС» на 30.05.2018.

В файле содержится следующая информация:

  • полный перечень участников СМЭВ и их информационных систем (вкладка «Статус Участника»)
  • полный перечень видов сведений с указанием поставщика, соответствующего сервиса СМЭВ2 (при наличии), а также статуса вывода ВС в тестовую и продуктивную среду (вкладка «Статус ВС»)

Этот документ является наиболее важным источником данных для поиска нужного вида сведений.

Алгоритм поиска вида сведений

Использование сводных файлов с перечнем видов сведений вместо веб-интерфейса существенно облегчает процесс поиска нужного ВС.

Сам алгоритм поиска выглядит следующим образом:

  1. Переходим на Технологический портал СМЭВ и скачиваем актуальную версию файла «Статус ВС»
  2. Производим поиск ВС, используя стандартный функционал поиска:
    1. по названию или SID соответствующего сервиса в СМЭВ2
    2. по ведомству-поставщику
    3. по ключевому слову
  3. Если в списке представлено несколько версий одного ВС — стоит использовать самую последнюю
  4. При наличии доступа к файлу «Единый отчет СМЭВ» стоит проверить, не входит ли вид сведений в число невостребованных

Как упоминалось выше, вывод вида сведений в продуктивную среду не гарантирует его фактическую работоспособность. Поэтому до старта полномасштабных работ по подключению и интеграции с ВС стоит провести дополнительную проверку:

  1. Протестировать ВС в тестовой среде
  2. Получить доступ к ВС в продуктивной среде
  3. Вручную сформировать несколько боевых запросов по схеме ВС
  4. Используя бесплатный клиент к СМЭВ направить в адрес Вида сведений эти боевые запросы в продуктивной среде
  5. Дождаться содержательны ответов на запросы (само собой, ответы с кодами ошибки или ответы с тестовыми данными не являются содержательными)

Только наличие содержательных ответов на запросы в продуктивной среде позволяет судить о реальной работоспособности Вида сведений СМЭВ 3 и может служить сигналом к началу работ по интеграции с ВС.


Система межведомственного электронного взаимодействия (СМЭВ) задумывалась как цифровая среда предоставления услуг и исполнения государственных и муниципальных функций в электронной форме.
В настоящее время СМЭВ продолжает расширять свои возможности и вовлекать все большее количество участников взаимодействия.
Что оказалось как нельзя кстати, в том числе для коммерческих организаций, в частности банков, которые все больше стремятся перевести свои услуги в цифру и сериализовать процессы.
В этой статье мы поговорим о том, как своими силами подписать запросы и проверить электронные подписи ответов СМЭВ версии 3.0, и о паре интересных нюансов, с которыми пришлось при этом столкнуться.
Здравствуйте!
Может возникнуть вопрос. Почему своими силами? Когда для СМЭВ 3 есть целый Технологический портал, где

  • опубликована вся документация и методические указания,
  • есть раздел с часто задаваемыми вопросами,
  • можно скачать актуальную версию библиотек клиента СМЭВ 3,
  • предоставлены примеры полных конвертов сообщений с подписями,
  • можно даже проверить онлайн свое сообщение или из примера на соответствие схемам сервиса СМЭВ и на предмет валидности его электронной подписи

Все верно, портал, безусловно, крайне полезный, и всеми его подсказками и инструментами можно и нужно пользоваться, но вот код на Java напишем свой.
По той простой причине, что уже есть собственная информационная система, работающая с форматами электронной подписи XMLDSig, XAdES, в которой применяются библиотеки проекта Apache Santuario, реализующие основные стандарты безопасности для XML. А также библиотеки, входящие в состав КриптоПро JCSP, помимо работы с XML, обеспечивающие API криптографических функций СКЗИ КриптоПро CSP.
Написание собственных методов для работы с электронными подписями СМЭВ 3 в данном случае выглядит более целесообразно, нежели разворачивание полного клиента поставляемого:
ФГБУ НИИ «Восход» (до 21 марта 2016 года ФГУП НИИ «Восход») или интеграция, его отдельных классов и пакетов.
В то же время заглянуть в открытый код клиента всегда полезно, а его наличие само по себе говорит о зрелости системы и высоком уровне поддержки.

Анализ исходных данных

Загружаем с портала СМЭВ 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 в файле \org\apache\xml\security\resource\config.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 выполняется успешно.
Сообщения проходят проверку на портале Электронного правительства Госуслуги

И в собственном приложении:

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *