Прочитать на английском

Поделиться через


Практическое руководство. Проверка цифровых подписей XML-документов

Классы в пространстве имен System.Security.Cryptography.Xml можно использовать для проверки XML-данных, подписанных цифровой подписью. Цифровые подписи XML (XMLDSIG) позволяют убедиться, что данные не были изменены после подписания. Дополнительные сведения о стандарте XMLDSIG см. в https://www.w3.org/TR/xmldsig-core/спецификации консорциума W3C .

Примечание

Код, приведенный в этой статье, применяется к Windows.

В примере кода в этой процедуре показано, как проверить цифровую подпись XML, содержащуюся в элементе <Signature> . Пример извлекает открытый ключ RSA из контейнера ключей и затем использует этот ключ для проверки подписи.

Сведения о создании цифровой подписи, которую можно проверить с помощью этого метода, см. в разделе "Практическое руководство. Подписывать XML-документы с помощью цифровых подписей".

Проверка цифровой подписи XML-документа

  1. Чтобы проверить документ, необходимо использовать тот же асимметричный ключ, который использовался для подписи. Создайте объект CspParameters и укажите имя контейнера ключей, который использовался для подписи.

    CspParameters cspParams = new()
    {
        KeyContainerName = "XML_DSIG_RSA_KEY"
    };
    
  2. Получите открытый ключ при помощи класса RSACryptoServiceProvider. Этот ключ автоматически загружается из контейнера ключей по имени при передаче объекта CspParameters в конструктор класса RSACryptoServiceProvider.

    RSACryptoServiceProvider rsaKey = new(cspParams);
    
  3. Создайте объект XmlDocument, загрузив XML-файл с диска. Объект XmlDocument содержит подписанный XML-документ, подлежащий проверке.

    XmlDocument xmlDoc = new()
    {
        // Load an XML file into the XmlDocument object.
        PreserveWhitespace = true
    };
    xmlDoc.Load("test.xml");
    
  4. Создайте новый объект SignedXml и передайте в него объект XmlDocument.

    SignedXml signedXml = new(xmlDoc);
    
  5. <signature> Найдите элемент и создайте новый XmlNodeList объект.

    XmlNodeList nodeList = xmlDoc.GetElementsByTagName("Signature");
    
  6. Загрузите XML-код первого <signature> элемента в SignedXml объект.

    signedXml.LoadXml((XmlElement?)nodeList[0]);
    
  7. Проверьте подпись, используя метод CheckSignature и открытый ключ RSA. Этот метод возвращает логическое значение, указывающее на успешное выполнение или сбой операции.

    return signedXml.CheckSignature(key);
    

Пример

В этом примере предполагается, что файл с именем "test.xml" существует в том же каталоге, что и скомпилированная программа. Файл "test.xml" должен быть подписан с помощью методов, описанных в разделе "Практическое руководство. Подписывать XML-документы с помощью цифровых подписей".

using System;
using System.Runtime.Versioning;
using System.Security.Cryptography;
using System.Security.Cryptography.Xml;
using System.Xml;

[SupportedOSPlatform("Windows")]
public class VerifyXML
{
    public static void Main(string[] args)
    {
        try
        {
            // Create a new CspParameters object to specify
            // a key container.
            CspParameters cspParams = new()
            {
                KeyContainerName = "XML_DSIG_RSA_KEY"
            };

            // Create a new RSA signing key and save it in the container.
            RSACryptoServiceProvider rsaKey = new(cspParams);

            // Create a new XML document.
            XmlDocument xmlDoc = new()
            {
                // Load an XML file into the XmlDocument object.
                PreserveWhitespace = true
            };
            xmlDoc.Load("test.xml");

            // Verify the signature of the signed XML.
            Console.WriteLine("Verifying signature...");
            bool result = VerifyXml(xmlDoc, rsaKey);

            // Display the results of the signature verification to
            // the console.
            if (result)
            {
                Console.WriteLine("The XML signature is valid.");
            }
            else
            {
                Console.WriteLine("The XML signature is not valid.");
            }
        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
        }
    }

    // Verify the signature of an XML file against an asymmetric
    // algorithm and return the result.
    public static bool VerifyXml(XmlDocument xmlDoc, RSA key)
    {
        // Check arguments.
        if (xmlDoc == null)
             throw new ArgumentException(null, nameof(xmlDoc));
        if (key == null)
            throw new ArgumentException(null, nameof(key));

        // Create a new SignedXml object and pass it
        // the XML document class.
        SignedXml signedXml = new(xmlDoc);

        // Find the "Signature" node and create a new
        // XmlNodeList object.
        XmlNodeList nodeList = xmlDoc.GetElementsByTagName("Signature");

        // Throw an exception if no signature was found.
        if (nodeList.Count <= 0)
        {
            throw new CryptographicException("Verification failed: No Signature was found in the document.");
        }

        // This example only supports one signature for
        // the entire XML document.  Throw an exception
        // if more than one signature was found.
        if (nodeList.Count >= 2)
        {
            throw new CryptographicException("Verification failed: More that one signature was found for the document.");
        }

        // Load the first <signature> node.
        signedXml.LoadXml((XmlElement?)nodeList[0]);

        // Check the signature and return the result.
        return signedXml.CheckSignature(key);
    }
}

Компиляция кода

Безопасность .NET

Не следует хранить или передавать закрытый ключ из пары асимметричных ключей в виде обычного текста. Дополнительные сведения о симметричных и асимметричных криптографических ключах см. в разделе "Создание ключей для шифрования и расшифровки".

Не следует внедрять закрытый ключ непосредственно в исходный код. Внедренные ключи можно легко считывать из сборки с помощью Ildasm.exe (IL Disassembler) или открытия сборки в текстовом редакторе, например Блокнот.

См. также