Ключевое слово в защите информации
КЛЮЧЕВОЕ СЛОВО
в защите информации
Получить ГОСТ TLS-сертификат для домена (SSL-сертификат)
Добро пожаловать, Гость! Чтобы использовать все возможности Вход или Регистрация.

Уведомление

Icon
Error

Опции
К последнему сообщению К первому непрочитанному
Offline Гребенсков  
#1 Оставлено : 22 июня 2012 г. 0:50:07(UTC)
Гребенсков

Статус: Новичок

Группы: Участники
Зарегистрирован: 22.06.2012(UTC)
Сообщений: 4
Откуда: Самара

С помощью примера в СДК SignSmevRequest.Он же указан по ссылке http://pastebin.com/vsYqqfMQ делаю подпись следующего сообщения:

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"><s:Header><Action s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://gucmp.ru/gosuslugi/ApprovalServiceSoap/CheckResponse</Action><h:Header xmlns:h="http://smev.gosuslugi.ru/rev111111" xmlns="http://smev.gosuslugi.ru/rev111111" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" /><h:Security xmlns:h="http://www.w3.org/2000/09/xmldsig#" xmlns="http://www.w3.org/2000/09/xmldsig#" /></s:Header><s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><CheckResponse xmlns="http://gucmp.ru/gosuslugi">
<CheckResult>
<Message xmlns="http://smev.gosuslugi.ru/rev111111">
<Date>0001-01-01T00:00:00</Date>
</Message>
<MessageData xmlns="http://smev.gosuslugi.ru/rev111111">
<AppData >
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#"/>
<XmlData xmlns="http://ws.ibs/Gucmp/CheckSignResponse">&lt;?xml version="1.0" encoding="utf-16"?&gt;&lt;root&gt;&lt;response errorCode="0" timestamp="2012-06-21T21:44:41.8175533+04:00" /&gt;&lt;data&gt;&lt;field name="ApprovalID"&gt;501adec6-03d0-4fa7-b062-71c6e9ab054c&lt;/field&gt;&lt;field name="Status"&gt;InProgress&lt;/field&gt;&lt;field name="DocNumber"&gt;124465-12&lt;/field&gt;&lt;field name="DocDate"&gt;2012-06-21T21:44:41.8175533+04:00&lt;/field&gt;&lt;field name="ApprovedPeriodFrom"&gt;2012-01-22T00:00:00.0000000&lt;/field&gt;&lt;field name="ApprovedPeriodTo"&gt;2012-02-22T00:00:00.0000000&lt;/field&gt;&lt;field name="ApprovedRoute"&gt;МО, Чеховский р-он, п.Столбовая: ул.Труда - Варшавское шоссе - а/д М-2 "Крым" - а/д А-108 МБК - а/д М-5 "Урал" - г.Рязань, ул.Новоселковая (ремонтная база)&lt;/field&gt;&lt;field name="SpecialConditions"&gt;1. Движение по искусственным сооружениям осуществлять в одиночном порядке.2. Движение по мостам и п/п со скоростью 15 км/ч.&lt;/field&gt;&lt;field name="PersonName"&gt;Иванов И.И.&lt;/field&gt;&lt;field name="PersonJob"&gt;Директор&lt;/field&gt;&lt;field name="Attachments"&gt;&lt;value&gt;&lt;file&gt;&lt;field name="Name"&gt;&lt;value /&gt;&lt;/field&gt;&lt;field name="FileName"&gt;&lt;value&gt;sample.txt&lt;/value&gt;&lt;/field&gt;&lt;field name="ContentType"&gt;&lt;value /&gt;&lt;/field&gt;&lt;field name="ContentLength"&gt;&lt;value&gt;0&lt;/value&gt;&lt;/field&gt;&lt;/file&gt;&lt;/value&gt;&lt;value&gt;&lt;file&gt;&lt;field name="Name"&gt;&lt;value /&gt;&lt;/field&gt;&lt;field name="FileName"&gt;&lt;value&gt;sample2.txt&lt;/value&gt;&lt;/field&gt;&lt;field name="ContentType"&gt;&lt;value /&gt;&lt;/field&gt;&lt;field name="ContentLength"&gt;&lt;value&gt;0&lt;/value&gt;&lt;/field&gt;&lt;/file&gt;&lt;/value&gt;&lt;/field&gt;&lt;/data&gt;&lt;/root&gt;</XmlData>
</AppData>
<AppDocument>
<RequestCode>req_ece3ce5a-2178-492f-8dc0-a4d0b7543742</RequestCode>
<BinaryData>UEsDBC0AAAAIAJSt1UAUtZpL//////////8KABQAc2FtcGxlLnR4dAEAEAAIAAAAAAAAAAQAAAAAAAAAK4YCAFBLAwQtAAAACACUrdVAP70X+fAA=</BinaryData>
</AppDocument>
</MessageData>
</CheckResult>
</CheckResponse>
</s:Body></s:Envelope>



Так вот.Проверка данного сообщения не проходит. Если использую другие файлы - подпись и проверка подписи проходят.
Было замечено, что в подписываемом сообщении есть тэг : <Signature xmlns="http://www.w3.org/2000/09/xmldsig#"/>
Который содержится в теле подписываемого сообщения. И если у данного тэга убрать неймспейс, то проверка нового сообщения работает.

Вопрос: как влияет присутствие пространства имён http://www.w3.org/2000/09/xmldsig# в теле подписываемого сообщения на валидацию?
Offline Максим Коллегин  
#2 Оставлено : 22 июня 2012 г. 4:15:59(UTC)
Максим Коллегин

Статус: Сотрудник

Группы: Администраторы
Зарегистрирован: 12.12.2007(UTC)
Сообщений: 6,393
Мужчина
Откуда: КРИПТО-ПРО

Сказал «Спасибо»: 37 раз
Поблагодарили: 717 раз в 621 постах
Возможно влияет на XML-валидацию - Вы какой валидатор/парсер используете?
Знания в базе знаний, поддержка в техподдержке
Offline Гребенсков  
#3 Оставлено : 22 июня 2012 г. 9:57:16(UTC)
Гребенсков

Статус: Новичок

Группы: Участники
Зарегистрирован: 22.06.2012(UTC)
Сообщений: 4
Откуда: Самара

Для проверки подписи использую код:

// Проверяет подписи в файле XML.
static void VerifyXmlFile(string SignedFileName)
{
// Создаем новый XML документ в памяти.
XmlDocument xmlDocument = new XmlDocument();

// Сохраняем все пробельные символы, они важны при проверке
// подписи.
xmlDocument.PreserveWhitespace = true;

// Загружаем подписанный документ из файла.
xmlDocument.Load(SignedFileName);

// Ищем все node "Signature" и сохраняем их в объекте XmlNodeList
XmlNodeList nodeList = (getHeaderNode (xmlDocument) as XmlElement).GetElementsByTagName(
"Signature", SignedXml.XmlDsigNamespaceUrl);

Console.WriteLine("Найдено:{0} подпис(ей).", nodeList.Count);

// Проверяем все подписи.
for (int curSignature = 0; curSignature < nodeList.Count; curSignature++)
{
// Создаем объект SignedXml для проверки подписи документа.
SmevSignedXml signedXml = new SmevSignedXml(xmlDocument);

// Загружаем узел с подписью.
signedXml.LoadXml((XmlElement)nodeList[curSignature]);

// SignXml самостоятельно не найдет сертификат подписи
// т.к. он лежит вне узла Signature.
// Поэтому самостоятельно извлечем сертификат по ссылке из KeyInfo
// и явно зададим открытый ключ для проверки подписи.
XmlNodeList referenceList = signedXml.KeyInfo.GetXml().GetElementsByTagName(
"Reference",
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");

if (referenceList.Count == 0)
{
throw new XmlException("Не удалось найти ссылку на сертификат");
}

// Ищем среди аттрибутов ссылку на сертификат.
string binaryTokenReference = null;
foreach (XmlAttribute attribute in referenceList[0].Attributes)
{
if (attribute.Name.ToUpper().Equals("URI"))
{
// Получаем ссылку на сертификат.
// формат #Value. '#' - нужно выбросить.
binaryTokenReference = attribute.Value.Substring(1);
break;
}
}

if (string.IsNullOrEmpty(binaryTokenReference))
{
throw new XmlException("Не удалось найти ссылку на сертификат");
}

// Получаем узел BinarySecurityToken с закодированным в base64 сертификатом
XmlElement binaryTokenElement = signedXml.GetIdElement(xmlDocument, binaryTokenReference);

if (binaryTokenElement == null)
{
throw new XmlException("Не удалось найти сертификат");
}

// Декодируем сертификат
byte[] certBytes = Convert.FromBase64String(binaryTokenElement.InnerText);
X509Certificate2 cert = new X509Certificate2();
cert.Import(certBytes);

// Проверяем подпись и выводим результат.
bool result = signedXml.CheckSignature(cert.PublicKey.Key);

// Выводим результат проверки подписи в консоль.
if (result)
Console.WriteLine("XML подпись[{0}] верна.", curSignature + 1);
else
Console.WriteLine("XML подпись[{0}] не верна.", curSignature + 1);
}
}
Offline Гребенсков  
#4 Оставлено : 22 июня 2012 г. 9:58:15(UTC)
Гребенсков

Статус: Новичок

Группы: Участники
Зарегистрирован: 22.06.2012(UTC)
Сообщений: 4
Откуда: Самара

Для создания подписи использую:


// Подписывает файл XML с помощью заданного сертификата и сохраняет подписанный документ
// в новый файл.
static string SignXmlFile(string forSign, X509Certificate2 Certificate)
{
// Создаем новый документ XML.
XmlDocument doc = new XmlDocument();
doc.PreserveWhitespace = false;

// Читаем документ из файла.
doc.LoadXml(forSign);

// Создаём объект SmevSignedXml - наследник класса SignedXml с перегруженным GetIdElement
// для корректной обработки атрибута wsu:Id.
SmevSignedXml signedXml = new SmevSignedXml(doc);

// Задаём ключ подписи для документа SmevSignedXml.
signedXml.SigningKey = Certificate.PrivateKey;

// Создаем ссылку на подписываемый узел XML. В данном примере и в методических
// рекомендациях СМЭВ подписываемый узел soapenv:Body помечен идентификатором "body".
Reference reference = new Reference();
reference.Uri = "#body";

// Задаём алгоритм хэширования подписываемого узла - ГОСТ Р 34.11-94. Необходимо
// использовать устаревший идентификатор данного алгоритма, т.к. именно такой
// идентификатор используется в СМЭВ.
#pragma warning disable 612
//warning CS0612: 'CryptoPro.Sharpei.Xml.CPSignedXml.XmlDsigGost3411UrlObsolete' is obsolete
reference.DigestMethod = CryptoPro.Sharpei.Xml.CPSignedXml.XmlDsigGost3411UrlObsolete;
#pragma warning restore 612

XmlDsigEnvelopedSignatureTransform env = new XmlDsigEnvelopedSignatureTransform();
reference.AddTransform(env);
XmlDsigExcC14NTransform c14 = new XmlDsigExcC14NTransform();
reference.AddTransform(c14);
signedXml.AddReference(reference);
KeyInfo keyInfo = new KeyInfo();
keyInfo.AddClause(new KeyInfoX509Data(Certificate));
signedXml.KeyInfo = keyInfo;
signedXml.SignedInfo.CanonicalizationMethod = c14.Algorithm;

// Задаём алгоритм подписи - ГОСТ Р 34.10-2001. Необходимо использовать устаревший
// идентификатор данного алгоритма, т.к. именно такой идентификатор используется в
// СМЭВ.
#pragma warning disable 612
//warning CS0612: 'CryptoPro.Sharpei.Xml.CPSignedXml.XmlDsigGost3411UrlObsolete' is obsolete
signedXml.SignedInfo.SignatureMethod = CryptoPro.Sharpei.Xml.CPSignedXml.XmlDsigGost3410UrlObsolete;
#pragma warning restore 612

// Вычисляем подпись.
signedXml.ComputeSignature();

// Получаем представление подписи в виде XML.
XmlElement xmlDigitalSignature = signedXml.GetXml();

// Добавляем необходимые узлы подписи в исходный документ в заготовленное место.
doc.GetElementsByTagName("ds:Signature")[0].PrependChild(
doc.ImportNode(xmlDigitalSignature.GetElementsByTagName("SignatureValue")[0], true));
doc.GetElementsByTagName("ds:Signature")[0].PrependChild(
doc.ImportNode(xmlDigitalSignature.GetElementsByTagName("SignedInfo")[0], true));

// Добавляем сертификат в исходный документ в заготовленный узел
// wsse:BinarySecurityToken.
doc.GetElementsByTagName("wsse:BinarySecurityToken")[0].InnerText =
xmlDigitalSignature.GetElementsByTagName("X509Certificate")[0].InnerText;

// Сохраняем подписанный документ в файл.
using (XmlTextWriter xmltw = new XmlTextWriter("signed.xml",
new UTF8Encoding(false)))
{
doc.WriteTo(xmltw);
}

return doc.InnerXml;
}
Offline Гребенсков  
#5 Оставлено : 22 июня 2012 г. 9:59:12(UTC)
Гребенсков

Статус: Новичок

Группы: Участники
Зарегистрирован: 22.06.2012(UTC)
Сообщений: 4
Откуда: Самара

В качестве парсера выступает стандартный .NET XmlDocument. Вопрос в том, что он внутри вызывает - пока не знаю. Если это нужно узнать, то напишите.
Offline khomenko  
#6 Оставлено : 22 июня 2012 г. 11:24:48(UTC)
Михаил Хоменко

Статус: Активный участник

Группы: Администраторы, Участники
Зарегистрирован: 28.04.2010(UTC)
Сообщений: 140
Мужчина
Откуда: Крипто-Про

Поблагодарили: 15 раз в 14 постах
Добрый день,

Если вы удалите пространство имен http://www.w3.org/2000/09/xmldsig# в узле Signature, то он будет "просто" узлом в теле сообщения, определенном в вашем пространстве имен xmlns="http://smev.gosuslugi.ru/rev111111"
А раз указано пространство имен http://www.w3.org/2000/09/xmldsig#, значит узел обрабатывается соответственно этой схеме. Сейчас он ей не соответствует: не хватает обязательных элементов: SignedInfo, SignatureValue и т. п.
В общем поведение XmlDocument корректно.
RSS Лента  Atom Лента
Пользователи, просматривающие эту тему
Guest
Быстрый переход  
Вы не можете создавать новые темы в этом форуме.
Вы не можете отвечать в этом форуме.
Вы не можете удалять Ваши сообщения в этом форуме.
Вы не можете редактировать Ваши сообщения в этом форуме.
Вы не можете создавать опросы в этом форуме.
Вы не можете голосовать в этом форуме.