private static bool VerifySmevRequestSignature(XmlDocument signedSmevRequest) { // Создание подписчика XML-документа var signedXml = new SmevSignedXml(signedSmevRequest); // { GetIdElementHandler = GetSmevIdElement }; // Поиск узла с подписью var nodeList = signedSmevRequest.GetElementsByTagName("Signature", SignedXml.XmlDsigNamespaceUrl); // Загрузка найденной подписи signedXml.LoadXml((XmlElement)nodeList[0]); // Поиск ссылки на BinarySecurityToken var references = signedXml.KeyInfo.GetXml().GetElementsByTagName("Reference", WsSecurityExtNamespace); if (references.Count > 0) { // Определение ссылки на сертификат (ссылка на узел документа) var binaryTokenReference = ((XmlElement)references[0]).GetAttribute("URI"); if (!String.IsNullOrEmpty(binaryTokenReference) && binaryTokenReference[0] == '#') { // Поиск элемента с закодированным в Base64 сертификатом var binaryTokenElement = signedXml.GetIdElement(signedSmevRequest, binaryTokenReference.Substring(1)); if (binaryTokenElement != null) { // Загрузка сертификата, который был использован для подписи var signingCertificate = new X509Certificate(Convert.FromBase64String(binaryTokenElement.InnerText)); // Проверка подписи return(signedXml.CheckSignature(signingCertificate.PublicKey.Key)); } } } return(false); }
// Проверяет подписи в файле XML. static void VerifyXmlFile(string SignedFileName) { // Создаем новый документ XML. XmlDocument xmlDocument = new XmlDocument(); // Форматируем документ с сохранением всех пробельных символов, т.к. они // важны при проверке подписи. xmlDocument.PreserveWhitespace = true; // Загружаем подписанный документ XML из файла. xmlDocument.Load(SignedFileName); // Ищем все узлы ds:Signature и сохраняем их в объекте XmlNodeList XmlNodeList nodeList = xmlDocument.GetElementsByTagName( "Signature", SignedXml.XmlDsigNamespaceUrl); Console.WriteLine("Найдено подписей: {0}.", nodeList.Count); // Проверяем все подписи. for (int curSignature = 0; curSignature < nodeList.Count; curSignature++) { // Создаём объект SmevSignedXml - наследник класса SignedXml с перегруженным // GetIdElement для корректной обработки атрибута wsu:Id. SmevSignedXml signedXml = new SmevSignedXml(xmlDocument); // Загружаем узел с подписью. signedXml.LoadXml((XmlElement)nodeList[curSignature]); // Получаем идентификатор ссылки на узел wsse:BinarySecurityToken, // содержащий сертификат подписи. XmlNodeList referenceList = signedXml.KeyInfo.GetXml().GetElementsByTagName( "Reference", WSSecurityWSSENamespaceUrl); if (referenceList.Count == 0) { throw new XmlException("Не удалось найти ссылку на сертификат"); } // Ищем среди аттрибутов ссылку на сертификат. string binaryTokenReference = ((XmlElement)referenceList[0]).GetAttribute("URI"); // Ссылка должна быть на узел внутри данного документа XML, т.е. она имеет вид // #ID, где ID - идентификатор целевого узла if (string.IsNullOrEmpty(binaryTokenReference) || binaryTokenReference[0] != '#') { throw new XmlException("Не удалось найти ссылку на сертификат"); } // Получаем узел BinarySecurityToken с закодированным в base64 сертификатом XmlElement binaryTokenElement = signedXml.GetIdElement( xmlDocument, binaryTokenReference.Substring(1)); if (binaryTokenElement == null) { throw new XmlException("Не удалось найти сертификат"); } // Создаём объект X509Certificate2 X509Certificate2 cert = new X509Certificate2(Convert.FromBase64String(binaryTokenElement.InnerText)); // Проверяем подпись. // ВНИМАНИЕ! Проверка сертификата в данном примере не осуществляется. Её необходимо // реализовать самостоятельно в соответствии с требованиями к подписи проверяемого // типа сообщения СМЭВ. bool result = signedXml.CheckSignature(cert.PublicKey.Key); // Выводим результат проверки подписи в консоль if (result) { Console.WriteLine("Подпись №{0} верна.", curSignature + 1); } else { Console.WriteLine("Подпись №{0} не верна.", curSignature + 1); } } }