Цифровая подпись Cades-BES для XML средствами 1С с помощью КриптоПро

Обработка иллюстрирует возможность подписания XML SOAP-конверта по стандарту Cades-BES средствами 1С с помощью внешней компоненты КриптоПРО «CAdESCOM» с учетом ГОСТ 2001 и ГОСТ 2012. Стандарт используется в различных механизмах государственных сайтов России, в том числе в СМЭВ и ГИС ЖКХ. Код не привязан к прикладному решению может быть встроен куда угодно, но только на платформе Windows.

Для работы с ГИС ЖКХ из 1С через API понадобилось выполнять цифровую подпись. Поначалу использовался OpenSSL + Python вот отсюда. Там сама подпись и контрольные суммы генерируются с помощью OpenSSL, а скрипт вставляет в исходный XML необходимые узлы.

Во-первых, все это работает через консоль, что не очень быстро. Во-вторых, OpenSSL принимает закрытый ключ в открытом PEM формате, что само по себе безобразие. В-третьих, с переходом на ГОСТ 2012 все это стало невозможно, поскольку инструментов извлечения закрытого ключа в формате PEM из сертификата, выполненного по ГОСТ 2012 не нашлось.

Штатный менеджер криптографии 1С помочь не может, так как подписывать XML не умеет, может только вернуть подпись для потока данных в формате CMS (базируется на PKCS#7), а необходима только сигнатура, длиной в 64 байта.

В итоге пришлось написать обработку, которая выполняет то же самое, что выполнял скрипт на Python.

Обработка подписывает стандартный SOAP-конверт <envelope>, для примера в ней есть тестовый запрос. Разумеется, для подписи в системе должен стоять КриптоПро, к нему должен быть подцеплен сертификат. Пробную версию КриптоПро можно скачать и установить бесплатно на официальном сайте. Тестовый сертификат можно выпустить там же, в тестовом удостоверяющем центре.

Для получения сигнатуры и хеша используется COM-объект "CAdESCOM", поставляемый вместе с КриптоПро. Менеджер криптографии 1С используется для получения данных сертификата — издателя и открытого ключа. Можно было бы обойтись без него, но с ним удобнее. Кроме того, используется COM-объект "System.Text.UTF8Encoding" для конвертации строки в массив байт COMSafeArray в кодировке UTF8. К сожалению, на выходе у XML полностью теряется форматирование. Избежать этого не получилось, так как оно уничтожается при каноникализации средствами 1С. Обратно возвращать форматирование уже нельзя, подпись становится невалидной.

Методика не привязана к конкретному прикладному решению и работает как на сервере, так и на клиенте. Тестировалось на релизе 8.3.13.1513. На более ранних будет работать вплоть до релиза, где есть МенеджерКриптографии, ДокументDOM, ДвоичныеДанные, ПреобразованиеККаноническомуXML и функции для работы с Base64.

P.S. Буду очень благодарен, если кто-нибудь сможет ответить на пару вопросов:

1. Так как используется COM, работать все это будет только на Windows. Если конвертацию в UTF8 можно переписать на 1С, то аналога CAdESCOM в Linux нет и не будет. Может, кто знает, как можно получить хеш и сигнатуру из КриптоПро в консоли на Linux.

2. Элемент подписи создается с помощью ДокументDOM фактически вручную, то есть поэтапным созданием каждого узла. Дописать в ДокументDOM кусок получилось из объекта ФабрикаXDTO, но началась путаница с пространствами имен и каноникализацией. Возможно, все-таки перепишу с использованием фабрики и макета. А вот вставить в один ДокументDOM кусок другого ДокументDOM, созданного из макета, у меня не получилось, хотя в СП такая возможность вроде как декларируется. Если кто подскажет, как — скажу спасибо.

P.P.S. Не на тему ЭЦП, но около. Если кто-нибудь озадачится вопросом создания туннеля по стандарту ГОСТ 2012, как этого требует ГИС ЖКХ и не только он, при наличии КриптоПро с этим отлично справляется их форк STunnel — stunnel-msspi. В него уже встроены необходимые алгоритмы, при этом нет необходимости вытаскивать ключ из КриптоПро и хранить его в открытом виде, как требуется в случае использования оригинального STunnel. Достаточно только указать открытый ключ сертификата или имя хранилища в КриптоПро.

27 Comments

  1. akela2014

    «Если кто-нибудь озадачится вопросом создания туннеля по стандарту ГОСТ 2012, как этого требует ГИС ЖКХ»©

    Интеграция в ГИС ЖКХ работает только с ГОСТ 2001 и неизвестно когда у них ГОСТ 2012 будет.

    Reply
  2. akela2014

    «поскольку инструментов извлечения закрытого ключа в формате PEM из сертификата, выполненного по ГОСТ 2012 не нашлось.»

    Есть такие

    http://www.lissi.ru/ls_product/utils/p12fromcsp/

    Reply
  3. akela2014

    Неожиданный ответ от поддержки ГИС ЖКХ получили )))

    ТО есть они уже сделали но как нам сделать не сказали)))

    «Поддержка стандарта усиленной квалифицированной электронной подписи ГОСТ Р 34.10-2012 «Информационная технология. Криптографическая защита информации. Процессы формирования и проверки электронной цифровой подписи» для организации шифрованного канала передачи данных при интеграционном взаимодействии, а также для подписания интеграционных пакетов в информационной системе жилищно-коммунального хозяйства (далее — система) осуществляется с версии системы 12.2.2.15.

    Поддержка ГОСТ Р 34.10-2001 в системе будет осуществляться до 31.12.2019.

    Дополнительно сообщаем, что в ближайшей версии системы в документации «Альбом ТФФ» будет добавлен пример запроса, подписанного с использованием сертификата с ГОСТ 34.10-2012 в пункт «2.2 Процедуры приема и передачи информации через SOAP веб-сервисы.».»©

    Reply
  4. PythonJ

    (3) Конечно уже работает. В районе января-февраля пробовал, тогда еще не работала. Узнал, что ГОСТ 2001 будет работать до конца года и махнул на это дело рукой. А вот недавно, в апреле 2019 одна из контор, с которой я работаю, перевыпустила сертификат. Выдали уже только один сертификат по ГОСТ 2012. В конце 2018 года выдавали сразу два по двум стандартам. Самое интересно, что в тот момент, когда выпустили новый сертификат, предыдущий по ГОСТ 2001 тут же оказался отозванным, хотя срок его действия на тот момент еще не истек. Пришлось в срочном порядке разбираться с ГОСТ 2012 и выяснилось, что ГИС ЖКХ тихой сапой уже включили его поддержку.

    Кстати, нам ответ прислали один в один такой же.

    Reply
  5. PythonJ

    (2) Из ГОСТ 2001 доставал PEM именно этой утилитой. На просторах Интернета нашлась. Но с ГОСТ 2012 не справилась. Можно, конечно, купить последнюю версию, но хранить ключ в PEM — по определению небезопасно. Да и зоопарк устраивать нет желания. OpenSSL из коробки ГОСТ 2012 не умеет. Надо собирать руками. STunnel — аналогично. Скрипт на Python работает с временными файлами, что само по себе не быстро. Кстати, не думаю, что в корпоративной среде допустимо использовать такие кулибинские методы для работы с криптографией.

    Проще и логичнее купить КриптоПро и решить все проблемы разом.

    Жалко вот, что подписывать получается только под Windows.

    Reply
  6. PythonJ

    Отвечу себе сам на вопрос по поводу COM и Windows.

    Все то, что сейчас выполняется средствами CadesCOM, можно выполнить консольными командами с помощью утилит cryptcp и csptest, которые будут работать не только в Windows. Cryptcp позволяет получить хеш-суммы и открепленную подпись. А с помощью csptest можно выдернуть из подписи сигнатуру в 64 байта.

    Ложка дегтя — в процессе одной подписи будут неоднократно использоваться временные файлы. Если количество сообщений ощутимое, из соображений быстродействия стоит создать RAM-диск маленького размера для этих файлов.

    Как только реализую подпись без COM-объектов — выложу. Заодно сравню скорость.

    Reply
  7. ЕлыПалы

    Добрый день! Скачали Вашу разработку «Цифровая подпись Cades-BES для XML средствами 1С с помощью КриптоПро» для подписи файлов для ГИС ЖКХ и сразу столкнулись с трудностями. При нажатии кнопки «Выбрать сертификат» и ответа на вопрос, что сертификат подписи находится на клиенте выдается ошибка «Возможно не установлен КРИПТО-ПРО или используется операционная система, отличная от Microsoft Windows». Хотя на компьютере установлена последняя версия 4.0.9944 (так утверждает админ, который сейчас находится в отпуске 🙂 Подскажите, что делать?

    Reply
  8. ЕлыПалы

    Какая-то мистика происходит. Компоненту установил, но результат тот же. Версия 1С:Предприятие 8.3 (8.3.12.1714). Попробовал подключить компоненту через 8.2. Работает. COM-объект успешно подключается. Сертификаты все отображаются в списке выбора. Подписать пока не получается в 8.2 по уже другим и понятным причинам.

    Reply
  9. ЕлыПалы

    Вот что выдает ОписаниеОшибки(): {ВнешняяОбработка.Подписать.Форма.Форма.Форма(41)}: Ошибка при вызове конструктора (COMОбъект): -2147221005(0x800401F3): Недопустимая строка с указанием класса

    Reply
  10. ЕлыПалы

    Есть подозрение, что причиной ошибки является то, что КриптоПро стоит на одном компьютере, а 1С стоит на другом сервере …

    Reply
  11. ЕлыПалы

    Попробовал установить в качестве эксперимента на компьютере где стоит КриптоПро файловую 1С и подписать сообщение. Все заработало

    Reply
  12. PythonJ

    КриптоПро и компонента CADeSCOM должны стоять на той машине, на которой осуществляется подпись. Если подпись выполняется на клиенте, то все это должно стоять на том компьютере, с которого запускается клиент. То есть на том, за которым вы открыли 1С. Сертификат в КриптоПро должен быть прицеплен к вашей учетной записи за этим ПК. Если подпись выполняется на сервере — ситуация совершенно иная.

    1. Сервер 1С должен работать под управлением MS Windows, так как если сервер работает под Linux, то о CADeSCOM можно забыть. COM-объектов там нету.

    2. КриптоПро и CADeSCOM должны стоять на сервере 1С. Обратите внимание, серверные версии КриптоПро, то есть которые можно поставить на Windows Server, стоят совершенно других денег. Если лицензия на обычный КриптоПро стоит порядка 2000 — 3000 руб, то серверная, насколько я помню, больше 40000.

    3. Cертификат должен быть прицеплен к КриптоПро на сервере к пользователю, под которым работает служба сервера 1С. Как правило USR1CV8. Тут возникает две проблемы. Во-первых, чтобы это сделать, нужно либо вручную править ветку реестра этого пользователя, либо временно дать ему право интерактивного входа в систему, зайти под ним и добавить сертификат. Вторая проблема хуже. Подобное решение — очень серьезная дыра в безопасности. Фактически, доступ к сертификату имеет любой пользователь, вошедший в 1С. Тут можно всякого разного придумать — защитить сертификат PIN-кодом, запретить выполнение обработок и т.д.

    В обработке я не ставил своей задачей грамотно решить вопрос безопасности в случае, когда подпись происходит на сервере.

    Reply
  13. ЕлыПалы

    Дмитрий, добрый день! На все запросы getStateRequest возвращает одну и ту же ошибку AUT011005 «Ошибка формата подписи запроса». Проверка этих запросов в SoapUI на валидность проходит на ура. Никаких претензий к запросам нет. Вы не сталкивались с такой проблемой?

    Reply
  14. ЕлыПалы

    Вот что на это отвечает служба поддержки ГИС ЖКХ:

    На текущий момент в приложенном Вами запросе возникает ошибка «AUT011005 Ошибка формата подписи запроса», которая отображается в связи с некорректной подписью запроса. В частности возникает проблема при обработке группы тегов xades:SigningCertificate.

    Во вложении предоставлен пример структуры электронного сообщения, подписанного по ГОСТ Р 34.11-2012/34.10-2012

    Reply
  15. PythonJ

    (14)

    Если один и тот же запрос при отправке из SoapUI отправляет корректно, а при отправке из 1С не работает, могу только предположить, что с запросом еще что-то происходит перед отправкой из 1С. Дело в том, что после подписи в теле запроса нельзя менять ни одного байта — подпись сразу станет невалидной. Даже перенос строки убрать/добавить нельзя. В настоящее время у меня работает отправка из 1С по ГОСТ 2012 без проблем. Нужно смотреть на код. Если хотите — сделайте демо-процедуру с подписью и отправкой с обращением, например, к nsi-common и пришлите.

    Reply
  16. PythonJ

    (14)

    Посмотрел внимательно на пример от СП ГИС ЖКХ. Странное дело. По логике вещей, моя обработка не должна бы работать, потому что кроме дайджеста самой подписи все хеширование выполняется старым алгоритмом ГОСТ 2001. Но тем не менее, у меня обмен работает. Видимо, перестанет после окончания поддержки в 2020 году. Поправлю обработку и сделаю все дайджесты одинаковыми. Спасибо за наводку.

    Reply
  17. ЕлыПалы

    Очередной ответ СП ГИС ЖКХ:

    Ошибка «AUT011005 Ошибка формата подписи запроса», при выполнении запроса, отобразилась в связи с некорректной подписью запроса. В частности возникает проблема при обработке группы тегов xades:SigningCertificate. Также просьба убедиться, что текст запроса не был изменён после его подписания. Для успешной отправки запроса не рекомендуется вносить изменения в подписанный запрос.

    Также для успешного выполнения запросов необходимо указать заголовок X-Client-Cert-Fingerprint актуального сертификата, которым и подписывается запрос.

    Подскажите, пожалуйста, в каком формате или кодировке этот отпечаток указывать в заголовке?

    Reply
  18. ЕлыПалы

    Хотя в документации написано следующее:

    «В случае установления нешифрованного соединения является обязательным добавление дополнительного http-заголовка X-Client-Cert-Fingerprint при отправке запроса на сервер. В качестве значения для данного заголовка необходимо указать отпечаток сертификата (в формате – без пробелов, например, 78302e3e47a4b7f5aac2f53bbcceb33bd12cbd16), который был указан в заявке на регистрацию ИС.»

    Причем здесь это, если канал шифрованный?…

    Reply
  19. ЕлыПалы

    Отослал в ГИС примеры запросов. Пришел ответ:

    Данная ошибка возникает в результате того, что подпись запроса вычислена некорректна: неверно рассчитано значение «DigestValue» в группе тегов «SigningCertificate».

    Напоминаем, что подпись запроса осуществляется на стороне приложения, при помощи которого осуществляется интеграционное взаимодействие с Системой. Приложенные к письму тексты запроса явно указывают на то, что для одного метода алгоритм подписания не реализован или не используется. Рекомендуем Вам ознакомиться с документацией «Демо-приложение по формированию и отправке запросов в ГИС ЖКХ на .NET» (Открытая часть Системы, раздел «Регламенты и инструкции»). В тексте документации содержится ссылка на исходный код утилиты для подписания xml файлов и soap запросов с применением алгоритмов ГОСТ, пример использования приложения и параметры конфигурации.

    Reply
  20. PythonJ

    Для работы с ГИС ЖКХ перед подписью необходимо проверить корректность исходного XML. Он должен быть канонизирован с исключающей каноникализацией. В обработке предполагается, что XML уже корректен. Если он создается с помощью XDTO, так оно и будет. Но если собирается «руками», то перед подписью нужно преобразовать его к каноническому виду. Иначе DigestValue получится некорректный.

    Reply
  21. user1029657

    в итоге получается ли подписывать 12 гостом?

    Reply
  22. PythonJ

    (21) Да. У вас не получилось?

    Reply
  23. user1029657

    мне походу не то скачали((просил вашу обработку

    Reply
  24. VVi3ard

    (5) Из моей практики для целей криптографии намного проще и эффективнее поставить рядом с Linux небольшую машину на Windows и опубликовать на ней http сервис прокси который будет подписывать данные.

    По работе с криптографией в линукс (уточню что с российской криптографией) информации не так и много.

    Если же говорить о инструментах самой КриптоПро то они только в консольном виде доступны, а при больших нагрузках это не так удобно.

    Если вы прям очень очень хотите на Линукс, то готового решения у меня нет, но частично информация есть тут:

    https://habr.com/ru/post/282225/

    Если это не для себя а для работы то я предпочел бы использовать mainstream инструменты с гарантированной поддержкой и стабильной работой.

    Но за статью огромное спасибо, еще в 2016 пытался сделать все что вы описали, но в итоге так и не смог штатными средствами получить XMLDSIG. А потом вопрос отпал и дальше копать не стал, но вообще уже на тот момент были мысли не мучать 1С а использовать прокси http сервис на C#

    Reply
  25. PythonJ

    (24) О да, если бы не получилось сделать в 1С — рядом бы прокси повесил, но это был последний вариант. Планируется перевод сервера на Linux — соответственно опять же, если не получится — будет рядом висеть виртуалка с Windows.

    Возможно в 2016 году в 1С это и не получилось бы. Не уверен, что все используемые объекты уже были и работали правильно. Не помню, с каких релизов стали поддерживать каноникализацию в более-менее разумных реализациях. Да и то что сейчас поддерживается — не все, что надо. Руками пришлось поправлять пространства имен.

    Статью на хабре эту уже вдоль и поперек прочитал, когда хотел без криптопро обойтись. Но это будет как раз «для себя» а не «для работы». Даже если сделать собственную реализацию, пользоваться ей в рабочих процессах не очень законно, как минимум. Вариант с КриптоПро предпочтительнее.

    Насчет «очень хочется на Линукс», скажем так, учитывая что 1С медленно но верно ползет к кросс-платформенности, меня сразу коробит от конструкции «Новый COMОбъект», когда нет даже приблизительных вариантов то же самое сделать без COM. То есть с КриптоПро, но без COM. А руками лезть в криптографию… Интересно, но бессмысленно с практической точки зрения.

    Reply
  26. Vyacheslav56

    скачал обработку, в моем сертификате нет Сертификат.Издатель.OU,но на ГИС заходит, не знаете почему?

    Reply
  27. PythonJ

    (26) В каком смысле «заходит»?

    Если я правильно понимаю, есть официальный сертификат без OU, и с ним можно авторизоваться в ЕСИА. Так?

    Но подписать запрос обработкой при этом не получается.

    Так? Странно.

    Не знаю, насколько там обязателен OU.

    Можете прислать открытую часть сертификата?

    Reply

Leave a Comment

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