Практическое руководство. Расшифровывание XML-элементов с помощью асимметричного ключа

Классы можно использовать в пространстве имен System.Security.Cryptography.Xml для шифрования и расшифровки элемента XML-документа. Шифрование XML-данных — это стандартный способ обмена зашифрованными XML-данными и их хранения, позволяющий не беспокоиться о том, что эти данные могут быть прочитаны. Дополнительные сведения о стандарте шифрования XML см. в рекомендации по синтаксису и обработке xml-подписей в консорциуме W3C.

Примечание.

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

В примере этой процедуры расшифровывается XML-элемент, зашифрованный с помощью методов, описанных в разделе "Практическое руководство. Шифрование XML-элементов с асимметричными ключами". Он находит <EncryptedData> элемент, расшифровывает элемент, а затем заменяет элемент исходным XML-элементом обычного текста.

Этот пример выполняет расшифровку XML-элемента с использованием двух ключей. Он извлекает ранее созданный закрытый ключ RSA из контейнера ключей, а затем использует ключ RSA для расшифровки ключа сеанса, хранящегося в <EncryptedKey> элементе <EncryptedData> элемента элемента. После этого пример использует сеансовый ключ для расшифровки XML-элемента.

Этот пример подходит в ситуациях, когда нескольким приложениям нужен общий доступ к зашифрованным данным или когда приложению требуется сохранять зашифрованные данные между запусками.

Расшифровка XML-элемента с использованием асимметричного ключа

  1. Создайте объект CspParameters и укажите имя контейнера ключей.

    CspParameters cspParams = new CspParameters();
    cspParams.KeyContainerName = "XML_ENC_RSA_KEY";
    
    Dim cspParams As New CspParameters()
    cspParams.KeyContainerName = "XML_ENC_RSA_KEY"
    
  2. Извлеките ранее созданный асимметричный ключ из контейнера при помощи объекта RSACryptoServiceProvider. Этот ключ автоматически извлекается из контейнера ключей по имени при передаче объекта CspParameters в конструктор RSACryptoServiceProvider.

    RSACryptoServiceProvider rsaKey = new RSACryptoServiceProvider(cspParams);
    
    Dim rsaKey As New RSACryptoServiceProvider(cspParams)
    
  3. Создайте новый объект EncryptedXml для расшифровки документа.

    // Create a new EncryptedXml object.
    EncryptedXml exml = new EncryptedXml(Doc);
    
    ' Create a new EncryptedXml object.
    Dim exml As New EncryptedXml(Doc)
    
  4. Добавьте сопоставление ключа и имени, чтобы связать ключ RSA с элементом в документе, который следует расшифровать. Для ключа необходимо использовать то же имя, которое использовалось при шифровании документа. Обратите внимание, что это имя отличается от имени, используемого для определения ключа в контейнере ключей, заданном на шаге 1.

    exml.AddKeyNameMapping(KeyName, Alg);
    
    exml.AddKeyNameMapping(KeyName, Alg)
    
  5. DecryptDocument Вызовите метод для расшифровки <EncryptedData> элемента. Этот метод использует ключ RSA для расшифровки сеансового ключа и автоматически использует этот сеансовый ключ для расшифровки XML-элемента. Он также автоматически заменяет <EncryptedData> элемент исходным открытым текстом.

    exml.DecryptDocument();
    
    exml.DecryptDocument()
    
  6. Сохраните XML-документ.

    xmlDoc.Save("test.xml");
    
    xmlDoc.Save("test.xml")
    

Пример

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


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

[SupportedOSPlatform("windows")]
class Program
{
    static void Main(string[] args)
    {
        // Create an XmlDocument object.
        XmlDocument xmlDoc = new XmlDocument();

        // Load an XML file into the XmlDocument object.
        try
        {
            xmlDoc.PreserveWhitespace = true;
            xmlDoc.Load("test.xml");
        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
        }
        CspParameters cspParams = new CspParameters();
        cspParams.KeyContainerName = "XML_ENC_RSA_KEY";

        // Get the RSA key from the key container.  This key will decrypt
        // a symmetric key that was imbedded in the XML document.
        RSACryptoServiceProvider rsaKey = new RSACryptoServiceProvider(cspParams);

        try
        {

            // Decrypt the elements.
            Decrypt(xmlDoc, rsaKey, "rsaKey");

            // Save the XML document.
            xmlDoc.Save("test.xml");

            // Display the encrypted XML to the console.
            Console.WriteLine();
            Console.WriteLine("Decrypted XML:");
            Console.WriteLine();
            Console.WriteLine(xmlDoc.OuterXml);
        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
        }
        finally
        {
            // Clear the RSA key.
            rsaKey.Clear();
        }

        Console.ReadLine();
    }

    public static void Decrypt(XmlDocument Doc, RSA Alg, string KeyName)
    {
        // Check the arguments.
        if (Doc == null)
            throw new ArgumentNullException("Doc");
        if (Alg == null)
            throw new ArgumentNullException("Alg");
        if (KeyName == null)
            throw new ArgumentNullException("KeyName");
        // Create a new EncryptedXml object.
        EncryptedXml exml = new EncryptedXml(Doc);

        // Add a key-name mapping.
        // This method can only decrypt documents
        // that present the specified key name.
        exml.AddKeyNameMapping(KeyName, Alg);

        // Decrypt the element.
        exml.DecryptDocument();
    }
}
Imports System.Xml
Imports System.Security.Cryptography
Imports System.Security.Cryptography.Xml

Module Program

    Sub Main(ByVal args() As String)

        ' Create an XmlDocument object.
        Dim xmlDoc As New XmlDocument()

        ' Load an XML file into the XmlDocument object.
        Try
            xmlDoc.PreserveWhitespace = True
            xmlDoc.Load("test.xml")
        Catch e As Exception
            Console.WriteLine(e.Message)
        End Try
        Dim cspParams As New CspParameters()
        cspParams.KeyContainerName = "XML_ENC_RSA_KEY"
        ' Get the RSA key from the key container.  This key will decrypt 
        ' a symmetric key that was imbedded in the XML document. 
        Dim rsaKey As New RSACryptoServiceProvider(cspParams)
        Try

            ' Decrypt the elements.
            Decrypt(xmlDoc, rsaKey, "rsaKey")

            ' Save the XML document.
            xmlDoc.Save("test.xml")
            ' Display the encrypted XML to the console.
            Console.WriteLine()
            Console.WriteLine("Decrypted XML:")
            Console.WriteLine()
            Console.WriteLine(xmlDoc.OuterXml)
        Catch e As Exception
            Console.WriteLine(e.Message)
        Finally
            ' Clear the RSA key.
            rsaKey.Clear()
        End Try


        Console.ReadLine()

    End Sub



    Sub Decrypt(ByVal Doc As XmlDocument, ByVal Alg As RSA, ByVal KeyName As String)
        ' Check the arguments.  
        ArgumentNullException.ThrowIfNull(Doc)
        ArgumentNullException.ThrowIfNull(Alg)
        ArgumentNullException.ThrowIfNull(KeyName)

        ' Create a new EncryptedXml object.
        Dim exml As New EncryptedXml(Doc)
        ' Add a key-name mapping.
        ' This method can only decrypt documents
        ' that present the specified key name.
        exml.AddKeyNameMapping(KeyName, Alg)
        ' Decrypt the element.
        exml.DecryptDocument()
    End Sub
End Module

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

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

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

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

После завершения работы с криптографическим ключом очистите его из памяти, установив для каждого байта нулевое значение или вызвав метод Clear управляемого класса шифрования. Иногда криптографические ключи можно считывать из памяти отладчиком или с жесткого диска, если область памяти выгружается на диск.

См. также