При подписании XML-фрагментов ЭП в формате XMLDSig, обязательно использование трансформации urn://smev-gov-ru/xmldsig/transform. Пример XML до и после трансформации по описанному ниже алгоритму приведены в Приложении Б.
Внимание! Алгоритм трансформации не применяется для графических объектов, описанных на языке идеограмм и пиктограмм (например, emoji). Перед трансформацией подобные объекты необходимо исключить из сообщения.
Алгоритм трансформации включает следующие шаги:
1. Удаления элементов XML declaration и processing instructions (при наличии)
вход:
<?xml version="1.0" encoding="UTF-8" ?> <?xml-stylesheet type="text/css" href="style.css"?> <qwe xmlns="http://t.e.s.t"> <myns:rty xmlns:myns="http://y.e.s">yes!</myns:rty> <iop value="yes, yes!"/> </qwe>
выход:
<qwe xmlns="http://t.e.s.t"> <myns:rty xmlns:myns="http://y.e.s">yes!</myns:rty> <iop value="yes, yes!"/> </qwe>
2. Удаление текстовых блоков (элементов XML), содержащих только пробельные символы. Если текстовый блок содержит только пробельные символы – u0009 - табуляция, u000A – перевод строки (Unix), u000D - возврат каретки, u0020, а также любые другие символы с кодом меньшим u0020, то все пробельные символы вырезаются. В результате данного преобразования достигается отсутствие пробельных символов.
вход:
<qwe xmlns="http://t.e.s.t"> <myns:rty xmlns:myns="http://y.e.s">yes!</myns:rty> <iop value=" test "/> </qwe>
выход:
<qwe xmlns="http://t.e.s.t"><myns:rty xmlns:myns="http://y.e.s">yes!</myns:rty><iop value=" test "/></qwe
3. После применения правил из пунктов 1 и 2, если даже у элемента нет дочерних узлов, элемент не может быть представлен в виде empty element tag (http://www.w3.org/TR/2008/REC-xml-20081126/#sec-starttags, правило [44]), выполняется преобразование элемента в пару start-tag + end-tag.
вход:
<qwe xmlns="http://t.e.s.t"> <myns:rty xmlns:myns="http://y.e.s">yes!</myns:rty> <iop value="yes, yes!"/> </qwe>
выход:
<qwe xmlns="http://t.e.s.t"> <myns:rty xmlns:myns="http://y.e.s">yes!</myns:rty> <iop value="yes, yes!"></iop> </qwe>
4. Удаление namespace prefix, которые на текущем уровне объявляются, но не используются в низлежащих тегах.
вход:
<qwe xmlns="http://t.e.s.t"> <myns:rty xmlns:myns=”http://y.e.s” myns:nouse=”http://nouse” >yes!</myns:rty> <iop value="yes, yes!"></iop> </qwe>
выход:
<qwe xmlns="http://t.e.s.t"> <myns:rty xmlns:myns="http://y.e.s">yes!</myns:rty> <iop value="yes, yes!"></iop> </qwe>
5. Проверка наличия объявления namespace текущего элемента либо в текущем элементе, либо выше по дереву. Если объявления namespase отсутствует, то объявление namespace выполняется в текущем элементе.
6. Namespace prefix элементов и атрибутов должны быть заменены на автоматически сгенерированные. Сгенерированный префикс состоит из литерала «ns», и порядкового номера сгенерированного префикса в рамках обрабатываемого XML-фрагмента, начиная с единицы. При генерации префиксов должно устраняться их дублирование.
вход:
<qwe xmlns="http://t.e.s.t"> <myns:rty xmlns:myns="http://y.e.s">yes!</myns:rty> <iop value="yes, yes!"/> </qwe>
выход:
<ns1:qwe xmlns:ns1="http://t.e.s.t"> <ns2:rty xmlns:ns2="http://y.e.s">yes!</ns2:rty> <ns1:iop value="yes, yes!"></ns1:iop> </ns1:qwe>
вход:
<nns:x xmlns:nns="http://a" attrB="value1" attrA="value2"> <y xmlns="http://a">yes!</y> </nns:x>
выход:
ns1:x xmlns:ns1="http://a" attrA="value2" attrB="value1"> <ns1:y>yes!</ns1:y> </ns1:x>
7. Атрибуты должны быть отсортированы в алфавитном порядке: сначала по namespace URI (если атрибут - в qualified form), затем – по local name. Атрибуты в unqualified form после сортировки идут после атрибутов в qualified form.
вход:
<nns:x xmlns:nns="http://a" attrB="value1" attrA="value2">
<y xmlns="http://a">yes!</y>
</nns:x>
выход:
<ns1:x xmlns:ns1="http://a" attrA="value2" attrB="value1">
<ns1:y>yes!</ns1:y>
</ns1:x>
8. Объявления namespace prefix должны находиться перед атрибутами. Объявления префиксов должны быть отсортированы в порядке объявления, а именно:
- Первым объявляется префикс пространства имён элемента, если он не был объявлен выше по дереву.
- Дальше объявляются префиксы пространств имён атрибутов, если они требуются. Порядок этих объявлений соответствует порядку атрибутов, отсортированных в алфавитном порядке (см. п.7 текущего перечня).
вход:
<tns:PERNAMEZPRequest xmlns:markcont="urn://x-artefacts-zags-pernamezp/markertypes/4.0.0" xmlns:tns="urn://x-artefacts-zags-pernamezp/4.0.0" xmlns:fnst="urn://x-artefacts-zags-pernamezp/types/4.0.0" xmlns:frgu="urn://x-artefacts-zags-pernamezp/frgutypes/4.0.0" markcont:ТипЗаявл="ФЛ" ЗаявлДата="2019-08-13" tns:ИдСвед="a" markcont:Заявление="15843" ДатаСвед="2018-08-13" frgu:КодУслуги="3482943">
выход (с учетом требований шагов 6, 7, 8 алгоритма трансформации):
<ns1:PERNAMEZPRequest xmlns:ns1="urn://x-artefacts-zags-pernamezp/4.0.0" xmlns:ns2="urn://x-artefacts-zags-pernamezp/frgutypes/4.0.0" xmlns:ns3="urn://x-artefacts-zags-pernamezp/markertypes/4.0.0" ns1:ИдСвед="a" ns2:КодУслуги="3482943" ns3:Заявление="15843" ns3:ТипЗаявл="ФЛ" ДатаСвед="2018-08-13" ЗаявлДата="2019-08-13">
9. Декодирование текста, реализуемое в СМЭВ с использованием библиотеки woodstox.
В рамках декодирования текста выполняется:
- Декодирование текстовых блоков (в элементах);
- Декодирование атрибутов.
a. Декодирование текстовых блоков
При декодировании текстовых блоков выполняется:
- Снятие экранирования символов по правилам;
- Разделения на части блоков, содержащих блоки символьных данных CDATA;
- Обработка блоков размером до 12 символов;
- Обработка блоков размером от 12 символов (включительно).
b. Снятие экранирования
Снятие экранирования выполняется в текстовых блоках, не содержащих блоков символьных данных по правилам, приведенным в таблице 11.
Таблица 11 - Правила снятия экранирования
№ |
Символ с экранированием |
Символ после снятия экранирования |
1. |
`
` |
` ` |
2. |
` ` |
` ` |
3. |
` ` |
` ` |
4. |
`
` |
` ` |
5. |
`	` |
` ` |
6. |
`	` |
` ` |
7. |
` ` |
` ` |
8. |
` ` |
` ` |
9. |
`>` |
`>` |
10. |
`<` |
`<` |
11. |
`&` |
`&` |
12. |
`'` |
`'` |
13. |
`"` |
`"` |
c. Разделение текстового блока, содержащего блок символьной информации CDATA
Тестовый блок, содержащий блок CDATA, разделяется на следующие блоки:- Текст до блока CDATA;
- Блок CDATA;
- Текст после блока CDATA.
В текстовых блоках, отличных от CDATA, полученных в результате разделения, выполняется снятие экранирования по правилам, приведенным в таблице 11. Для блока символьных (CDATA) данных снятие экранирования и последующее кодирование не выполняются.
Примечание: После завершения кодировки текстовые блоки, разделенные на части, соединяются.
d. Обработка блоков размером до 11 символов (включительно).
После снятия экранирования выполняется кодирование текста по правилам, приведенным в таблице 12.
Таблица 12 - Кодирование блоков размером до 12 символов.
№ |
Кодируемый символ |
Значение после кодирования |
Условия кодирования |
1. |
`<` |
`<` |
всегда |
2. |
`&` |
`&` |
всегда |
3. |
` ` |
`
` |
всегда |
4. |
`>` |
`>` |
если первый символ в блоке (включая пробелы и переводы строк) или после символа `]` |
e. Обработка блоков размером от 12 символов (включительно).
Блоки размером от 12 символов, разделяются на части по 512 символов.
Примечание: Если блок больше или равен 12 символов и не превосходит 512 символов, то блок не разделяется.
В каждой из частей блок выполняется кодирование по правилам, приведенным в таблице 13.
Таблица 13 - Правила кодирования блока размером от 12 символов (включительно).
№ |
Кодируемый символ |
Значение после кодирования |
Условия кодирования |
1. |
`<` |
`<` |
всегда |
2. |
`&` |
`&` |
всегда |
3. |
` ` |
`
` |
всегда |
4. |
`>` |
`>` |
если первый символ в блоке (с учетом пробелов и переводов строк) или после символов `<`, `>`, `&`, `]` |
Примечание: После завершения кодировки текстовые блоки, разделенные на части, соединяются.
f. Декодирование атрибутов
Декодирование атрибутов XML выполняется в 2 этапа:
- Снятие экранирования и замена пробельных символов пробелом;
- Кодирование атрибутов.
В атрибутах XML сообщения выполняется замена пробельных символов (перевод строки, пробел, символ перевода каретки, табуляция) на пробел.
Снятие экранирования выполняется по правилам, приведенным в таблице 11.
Кодирование атрибутов выполняется в соответствии с правилами, указанными в таблице 14
Таблица 14 - Правила снятия экранирования
№ |
Символ с экранированием |
Символ после снятия экранирования |
1. |
`
` |
` ` |
2. |
` ` |
` ` |
3. |
` ` |
` ` |
4. |
`
` |
` ` |
5. |
`	` |
` ` |
6. |
`	` |
` ` |
7. |
` ` |
` ` (символ пробела) |
8. |
` ` |
` ` (символ пробела) |
9. |
` ` |
` ` (символ пробела) |
10. |
` ` |
` ` (символ пробела) |
11. |
`>` |
`>` |
12. |
`<` |
`<` |
13. |
`&` |
`&` |
14. |
`'` |
`'` |
15. |
`"` |
`"` |
Кодирование атрибутов выполняется в соответствии с правилами, указанными в таблице 15
Таблица 15 - Правила снятия экранирования в атрибутах XML-сообщения.
№ |
Кодируемый символ |
Значение после кодирования |
Условия кодирования |
1. |
`<` |
`<` |
всегда |
2. |
`&` |
`&` |
всегда |
3. |
`"` |
`"` |
всегда |
4. |
` ` |
`
` |
всегда |
5. |
` ` |
`
` |
всегда |
6. |
` ` |
`	` |
всегда |
Развёрнутый пример результата трансформации XML представлен в приложении Б. Образцовая реализация алгоритма на Java для Apache Santuario представлена в приложении Г.
Сценарии тестирования алгоритма приведены в приложении Д. Для использования сценариев их необходимо сохранить в файлах в кодировке UTF-8.