Автор: PaulIsh 
Добрый день.
Пытаемся повторить весь процесс на web используя
http://gostcrypto.com/Также столкнулись с неясностью алгоритма.
Как мы видим процесс:
1. Формируем UKM (случайные 8 байт)
2. Формируем KEK (ключ шифрования ключа) используя публичный ключ ФСС, наш закрытый ключ и UKM алгоритмом VKO GOST R 34.10-2001
3. Формируем CEK (ключ шифрования содержимого) для GOST 28147
4. Шифруем данные по GOST 28147
5. Шифруем ключ CEK используя KEK и UKM по GOST 28147-89 key wrap
Далее для XML сцепляем UKM и данные и переводим в base64, также в base64 переводим зашифрованный ключ.
ФСС нам выдает ошибку. Что мы делаем не так?
Да проблему решил и алгоритм работает на тестовом контуре в двух вариантах с шифрованием и без.
Основные проблемы возникавшие - это отступление от шаблона (XML документа) указанного в спецификации (
упущено явное указание простраства имен тэгов,
изменен порядок следования узлов,
упущена замена стандартной информации сформированной на требуемую по спецификации).
Могу лишь описать как на C# выполнялось, основа подхода работы бралась из примера "C:\Program Files\Crypto Pro\.NET SDK\Examples\simple.zip\Xml\cs\EncryptCerts.cs":
1. Создаем XML документ соответствующий структуре по спецификации п.4.4.
2. Накладываем ЭЦП на содержимое узла "<soapenv:Body wsu:Id="REGNO_#########">. Пришлось использовать измененный SignedXml по причине наличия требования в спецификации явных пространств имен, пример есть на "http://cryptopro.ru/blog/2012/05/16/podpis-soobshchenii-soap-dlya-smev-s-ispolzovaniem-kriptopro-net", а стандартный SignedXml не умеет подписывать с пространством имен, что приводило либо к ошибкам, либо не соответствие подписи и содержимого.
2.1. Результат работы ЭЦП -> содрежимое узлов "wsse:BinarySecurityToken", "SignatureValue", "SignedInfo" и в общем всего что необходимо по спецификации -> добавляем в документ из (п.1). Это необходимо по причине того (возможно только в C#), что созданный XML блок в результате подписи не соответствует требуемой по спецификации ФСС структуре XML.
3. Шифрование.
3.1. Создаем документ XML соответствующий структуре по спецификации (п.5.1..) Обратим внимание что в спецификации есть "косяк" с тэгами узлов "<soapenv:Body>" и "</SOAP-ENV:Body>". Мы использовали соответствие общей структруе "<soapenv:Body>" а зашифрованная структура "</xenc:EncryptedData>" содержалась внутри "<soapenv:Body>".
3.2. Конечный документ из (п.2.) шифруем.
3.2.1. Получаем (X509Certificate2) публичную часть сертификата получателя (ФСС тестовый контур) из хранилища на локальном ПК.
3.2.2. Используя шифровщик XML "EncryptedXml" создаем блок зашифрованных данных "EncryptedData" (EncryptedData EncryptedData = EncryptedXml.Encrypt(XmlElement, CertificateEncrypt);). В качестве XmlElement указывался "<soapenv:Body>" из конечного документа из (п.2.).
3.2.3. Для EncryptedData указываем свойства: Type = "CryptoAlgoritm.GOST28147_89" (берется из библиотеки CryptoPro), EncryptionMethod = new EncryptionMethod(CPEncryptedXml.XmlEncGost28147Url)
3.2.4. Получаем результирующий XML зашифрованных данных из EncryptedData (XmlElement EncryptedElement = EncryptedData.GetXml();).
3.3. Опять из-за разницы требований спецификации и результатов полученных шифрованием, данные из (п.3.2.4.) подставляем в соответствующие тэги созданные в документе в (п.3.1.) и получаем итоговый зашифрованный документ готовый к отправке (пример XSLT шаблона для трансформации на C#):
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes" encoding="utf-8"/>
<xsl:template match="/">
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header>
</soapenv:Header>
<soapenv:Body>
<xenc:EncryptedData xmlns:xenc="http://www.w3.org/2001/04/xmlenc#" Type="http://www.w3.org/2001/04/xmlenc#Content" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:sch="http://gost34.ibs.ru/WrapperService/Schema" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<xenc:EncryptionMethod Algorithm="urn:ietf:params:xml:ns:cpxmlsec:algorithms:gost28147"/>
<ds:KeyInfo>
<xenc:EncryptedKey xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
<xenc:EncryptionMethod Algorithm="urn:ietf:params:xml:ns:cpxmlsec:algorithms:transport-gost2001"/>
<ds:KeyInfo>
<ds:X509Data>
<ds:X509Certificate>
<xsl:value-of select="/xenc:EncryptedData/ds:KeyInfo/xenc:EncryptedKey/ds:KeyInfo/ds:X509Data/ds:X509Certificate"/>
</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
<xenc:CipherData>
<xenc:CipherValue>
<xsl:value-of select="/xenc:EncryptedData/ds:KeyInfo/xenc:EncryptedKey/xenc:CipherData/xenc:CipherValue"/>
</xenc:CipherValue>
</xenc:CipherData>
</xenc:EncryptedKey>
</ds:KeyInfo>
<xenc:CipherData>
<xenc:CipherValue>
<xsl:value-of select="/xenc:EncryptedData/xenc:CipherData/xenc:CipherValue"/>
</xenc:CipherValue>
</xenc:CipherData>
</xenc:EncryptedData>
</soapenv:Body>
</soapenv:Envelope>
</xsl:template>
</xsl:stylesheet>
4. По требованию спецификации необходимо в отправляемом сообщении указать свой публичный сертификат, поэтому заменяем информацию сертификата в узле "/soapenv:Envelope/soapenv:Body/xenc:EncryptedData/ds:KeyInfo/xenc:EncryptedKey/ds:KeyInfo/ds:X509Data/ds:X509Certificate" на свой сертификат (им будет шифроваться ответ от сервера), остальную часть "xenc:EncryptedData" не трогаем.
PS (касаемо C#): никаких самостоятельных формирований ключа и т.п. не производили(все необходимые ключи есть в сертификате), все выполнялось стандартными средствами криптографии и подключенными библиотеками CryptoPro:
using CryptoPro.Sharpei;
using CryptoPro.Sharpei.Xml;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Security.Cryptography.Xml;
Отредактировано пользователем 4 апреля 2018 г. 9:27:23(UTC)
| Причина: Выделение основных проблем.