Практическое руководство. Расшифровывание XML-элементов с помощью асимметричного ключа
Классы можно использовать в пространстве имен System.Security.Cryptography.Xml для шифрования и расшифровки элемента XML-документа. Шифрование XML-данных — это стандартный способ обмена зашифрованными XML-данными и их хранения, позволяющий не беспокоиться о том, что эти данные могут быть прочитаны. Дополнительные сведения о стандарте шифрования XML см. в рекомендации по синтаксису и обработке xml-подписей в консорциуме W3C.
Примечание.
Код, приведенный в этой статье, применяется к Windows.
В примере этой процедуры расшифровывается XML-элемент, зашифрованный с помощью методов, описанных в разделе "Практическое руководство. Шифрование XML-элементов с асимметричными ключами". Он находит <EncryptedData
> элемент, расшифровывает элемент, а затем заменяет элемент исходным XML-элементом обычного текста.
Этот пример выполняет расшифровку XML-элемента с использованием двух ключей. Он извлекает ранее созданный закрытый ключ RSA из контейнера ключей, а затем использует ключ RSA для расшифровки ключа сеанса, хранящегося в <EncryptedKey
> элементе <EncryptedData
> элемента элемента. После этого пример использует сеансовый ключ для расшифровки XML-элемента.
Этот пример подходит в ситуациях, когда нескольким приложениям нужен общий доступ к зашифрованным данным или когда приложению требуется сохранять зашифрованные данные между запусками.
Расшифровка XML-элемента с использованием асимметричного ключа
Создайте объект CspParameters и укажите имя контейнера ключей.
CspParameters cspParams = new CspParameters(); cspParams.KeyContainerName = "XML_ENC_RSA_KEY";
Dim cspParams As New CspParameters() cspParams.KeyContainerName = "XML_ENC_RSA_KEY"
Извлеките ранее созданный асимметричный ключ из контейнера при помощи объекта RSACryptoServiceProvider. Этот ключ автоматически извлекается из контейнера ключей по имени при передаче объекта CspParameters в конструктор RSACryptoServiceProvider.
RSACryptoServiceProvider rsaKey = new RSACryptoServiceProvider(cspParams);
Dim rsaKey As New RSACryptoServiceProvider(cspParams)
Создайте новый объект EncryptedXml для расшифровки документа.
// Create a new EncryptedXml object. EncryptedXml exml = new EncryptedXml(Doc);
' Create a new EncryptedXml object. Dim exml As New EncryptedXml(Doc)
Добавьте сопоставление ключа и имени, чтобы связать ключ RSA с элементом в документе, который следует расшифровать. Для ключа необходимо использовать то же имя, которое использовалось при шифровании документа. Обратите внимание, что это имя отличается от имени, используемого для определения ключа в контейнере ключей, заданном на шаге 1.
exml.AddKeyNameMapping(KeyName, Alg);
exml.AddKeyNameMapping(KeyName, Alg)
DecryptDocument Вызовите метод для расшифровки <
EncryptedData
> элемента. Этот метод использует ключ RSA для расшифровки сеансового ключа и автоматически использует этот сеансовый ключ для расшифровки XML-элемента. Он также автоматически заменяет <EncryptedData
> элемент исходным открытым текстом.exml.DecryptDocument();
exml.DecryptDocument()
Сохраните 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 Framework, добавьте ссылку на
System.Security.dll
.В проекте, который предназначен для .NET Core или .NET 5, установите пакет NuGet System.Security.Cryptography.Xml.
Включите следующие пространства имен: System.Xml, System.Security.Cryptography и System.Security.Cryptography.Xml.
Безопасность .NET
Никогда не храните симметричный криптографический ключ в формате обычного текста и не передавайте этот симметричный ключ в таком формате между компьютерами. Кроме того, не следует хранить или передавать закрытый ключ из пары асимметричных ключей в виде обычного текста. Дополнительные сведения о симметричных и асимметричных криптографических ключах см. в разделе "Создание ключей для шифрования и расшифровки".
Не следует внедрять ключ непосредственно в исходный код. Внедренные ключи можно легко считывать из сборки с помощью Ildasm.exe (IL Disassembler) или открытия сборки в текстовом редакторе, например Блокнот.
После завершения работы с криптографическим ключом очистите его из памяти, установив для каждого байта нулевое значение или вызвав метод Clear управляемого класса шифрования. Иногда криптографические ключи можно считывать из памяти отладчиком или с жесткого диска, если область памяти выгружается на диск.