Практическое руководство. Шифрование XML-элементов с помощью сертификатов X.509
Обновлен: Ноябрь 2007
Классы пространства имен System.Security.Cryptography.Xml могут использоваться для шифрования элементов в XML-документе. Шифрование XML-данных является стандартным способом обмена и хранения XML-данных, защищающим их от несанкционированного прочтения. Дополнительные сведения о стандарте шифрования XML-данных см. в спецификации консорциума W3C по шифрованию XML-данных, расположенной на веб-узле по адресу: http://www.w3.org/TR/xmldsig-core/.
С помощью шифрования XML-данных можно заменить любой XML-элемент или документ элементом EncryptedData, содержащим зашифрованные XML-данные. Элемент EncryptedData может включать вложенные элементы, содержащие сведения о ключах и процессах, которые были использованы при шифровании. Шифрование XML-данных позволяет производить шифрование нескольких элементов внутри одного документа, а также многократное шифрование одного элемента. Пример кода, приводимый в данной процедуре, демонстрирует способ создания элемента EncryptedData с одновременным созданием нескольких вложенных элементов, которые могут использоваться далее в процессе шифрования.
В этом примере шифрование XML-элемента производится с использованием двух ключей. В нем с помощью Средство создания сертификатов (Makecert.exe) создается тестовый сертификат X.509, который затем сохраняется в хранилище сертификатов. Далее выполняется программное извлечение сертификата, который используется для шифрования XML-элемента с помощью метода Encrypt. Внутренне метод Encrypt создает отдельный ключ сеанса, который затем использует для шифрования XML-документа. Этот метод зашифровывает ключ сеанса и сохраняет его вместе с зашифрованным XML-элементом в новом элементе EncryptedData.
Для расшифровки XML-элемента необходимо просто вызвать метод DecryptDocument, который автоматически извлечет сертификат X.509 из хранилища и выполнит требуемую расшифровку. Дополнительные сведения о способах расшифровки XML-элементов, зашифрованных с помощью данной процедуры, см. в разделе Практическое руководство. Расшифровка XML-элементов с помощью сертификатов X.509.
Этот пример применим в том случае, если необходимо обеспечить общий доступ к зашифрованным данным со стороны нескольких приложений, или если приложение должно сохранять зашифрованные данные между запусками.
Шифрование XML-элемента с помощью сертификата X.509
Воспользуйтесь Средство создания сертификатов (Makecert.exe) для создания тестового сертификата X.509 и разместите его в хранилище локального пользователя. Необходимо создать ключ обмена и сделать его экспортируемым. Выполните следующую команду:
makecert -r -pe -n "CN=XML_ENC_TEST_CERT" -b 01/01/2005 -e 01/01/2010 -sky exchange -ss my
Создайте объект X509Store и инициализируйте его, чтобы открыть хранилище текущего пользователя.
Dim store As New X509Store(StoreLocation.CurrentUser)
X509Store store = new X509Store(StoreLocation.CurrentUser);
Откройте хранилище в режиме "только для чтения".
store.Open(OpenFlags.ReadOnly)
store.Open(OpenFlags.ReadOnly);
Инициализируйте коллекцию X509Certificate2Collection, включив в нее все сертификаты, размещенные в хранилище.
Dim certCollection As X509Certificate2Collection = store.Certificates
X509Certificate2Collection certCollection = store.Certificates;
Выполните перебор сертификатов, размещенных в хранилище, чтобы найти сертификат с соответствующим именем. В этом примере сертификат имеет имя "CN=XML_ENC_TEST_CERT".
Dim cert As X509Certificate2 = Nothing ' Loop through each certificate and find the certificate ' with the appropriate name. Dim c As X509Certificate2 For Each c In certCollection If c.Subject = "CN=XML_ENC_TEST_CERT" Then cert = c Exit For End If Next c
X509Certificate2 cert = null; // Loop through each certificate and find the certificate // with the appropriate name. foreach (X509Certificate2 c in certCollection) { if (c.Subject == "CN=XML_ENC_TEST_CERT") { cert = c; break; } }
После нахождения нужного сертификата закройте хранилище.
store.Close()
store.Close();
Создайте объект XmlDocument путем загрузки XML-файла с диска. Объект XmlDocument содержит XML-элемент, подлежащий шифрованию.
Dim xmlDoc As New XmlDocument()
XmlDocument xmlDoc = new XmlDocument();
Найдите указанный элемент в объекте XmlDocument и создайте новый объект XmlElement, который будет представлять элемент, подлежащий шифрованию. В этом примере производится шифрование элемента "creditcard".
Dim elementToEncrypt As XmlElement = Doc.GetElementsByTagName(ElementToEncryptName)(0)
XmlElement elementToEncrypt = Doc.GetElementsByTagName(ElementToEncrypt)[0] as XmlElement;
Создайте новый экземпляр класса EncryptedXml и используйте его для шифрования указанного элемента с помощью сертификата X.509. Метод Encrypt возвращает зашифрованный элемент в виде объекта EncryptedData.
Dim eXml As New EncryptedXml() ' Encrypt the element. Dim edElement As EncryptedData = eXml.Encrypt(elementToEncrypt, Cert)
EncryptedXml eXml = new EncryptedXml(); // Encrypt the element. EncryptedData edElement = eXml.Encrypt(elementToEncrypt, Cert);
Замените элемент из исходного объекта XmlDocument элементом EncryptedData.
EncryptedXml.ReplaceElement(elementToEncrypt, edElement, False)
EncryptedXml.ReplaceElement(elementToEncrypt, edElement, false);
Сохраните объект XmlDocument.
xmlDoc.Save("test.xml")
xmlDoc.Save("test.xml");
Пример
Imports System
Imports System.Xml
Imports System.Security.Cryptography
Imports System.Security.Cryptography.Xml
Imports System.Security.Cryptography.X509Certificates
Module Program
Sub Main(ByVal args() As String)
Try
' Create an XmlDocument object.
Dim xmlDoc As New XmlDocument()
' Load an XML file into the XmlDocument object.
xmlDoc.PreserveWhitespace = True
xmlDoc.Load("test.xml")
' Open the X.509 "Current User" store in read only mode.
Dim store As New X509Store(StoreLocation.CurrentUser)
store.Open(OpenFlags.ReadOnly)
' Place all certificates in an X509Certificate2Collection object.
Dim certCollection As X509Certificate2Collection = store.Certificates
Dim cert As X509Certificate2 = Nothing
' Loop through each certificate and find the certificate
' with the appropriate name.
Dim c As X509Certificate2
For Each c In certCollection
If c.Subject = "CN=XML_ENC_TEST_CERT" Then
cert = c
Exit For
End If
Next c
If cert Is Nothing Then
Throw New CryptographicException("The X.509 certificate could not be found.")
End If
' Close the store.
store.Close()
' Encrypt the "creditcard" element.
Encrypt(xmlDoc, "creditcard", cert)
' Save the XML document.
xmlDoc.Save("test.xml")
' Display the encrypted XML to the console.
Console.WriteLine("Encrypted XML:")
Console.WriteLine()
Console.WriteLine(xmlDoc.OuterXml)
Catch e As Exception
Console.WriteLine(e.Message)
End Try
End Sub 'Main
Sub Encrypt(ByVal Doc As XmlDocument, ByVal ElementToEncryptName As String, ByVal Cert As X509Certificate2)
' Check the arguments.
If Doc Is Nothing Then
Throw New ArgumentNullException("Doc")
End If
If ElementToEncryptName Is Nothing Then
Throw New ArgumentNullException("ElementToEncrypt")
End If
If Cert Is Nothing Then
Throw New ArgumentNullException("Cert")
End If
''''''''''''''''''''''''''''''''''''''''''''''''
' Find the specified element in the XmlDocument
' object and create a new XmlElemnt object.
''''''''''''''''''''''''''''''''''''''''''''''''
Dim elementToEncrypt As XmlElement = Doc.GetElementsByTagName(ElementToEncryptName)(0)
' Throw an XmlException if the element was not found.
If elementToEncrypt Is Nothing Then
Throw New XmlException("The specified element was not found")
End If
''''''''''''''''''''''''''''''''''''''''''''''''
' Create a new instance of the EncryptedXml class
' and use it to encrypt the XmlElement with the
' X.509 Certificate.
''''''''''''''''''''''''''''''''''''''''''''''''
Dim eXml As New EncryptedXml()
' Encrypt the element.
Dim edElement As EncryptedData = eXml.Encrypt(elementToEncrypt, Cert)
''''''''''''''''''''''''''''''''''''''''''''''''
' Replace the element from the original XmlDocument
' object with the EncryptedData element.
''''''''''''''''''''''''''''''''''''''''''''''''
EncryptedXml.ReplaceElement(elementToEncrypt, edElement, False)
End Sub
End Module
using System;
using System.Xml;
using System.Security.Cryptography;
using System.Security.Cryptography.Xml;
using System.Security.Cryptography.X509Certificates;
class Program
{
static void Main(string[] args)
{
try
{
// Create an XmlDocument object.
XmlDocument xmlDoc = new XmlDocument();
// Load an XML file into the XmlDocument object.
xmlDoc.PreserveWhitespace = true;
xmlDoc.Load("test.xml");
// Open the X.509 "Current User" store in read only mode.
X509Store store = new X509Store(StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadOnly);
// Place all certificates in an X509Certificate2Collection object.
X509Certificate2Collection certCollection = store.Certificates;
X509Certificate2 cert = null;
// Loop through each certificate and find the certificate
// with the appropriate name.
foreach (X509Certificate2 c in certCollection)
{
if (c.Subject == "CN=XML_ENC_TEST_CERT")
{
cert = c;
break;
}
}
if (cert == null)
{
throw new CryptographicException("The X.509 certificate could not be found.");
}
// Close the store.
store.Close();
// Encrypt the "creditcard" element.
Encrypt(xmlDoc, "creditcard", cert);
// Save the XML document.
xmlDoc.Save("test.xml");
// Display the encrypted XML to the console.
Console.WriteLine("Encrypted XML:");
Console.WriteLine();
Console.WriteLine(xmlDoc.OuterXml);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
public static void Encrypt(XmlDocument Doc, string ElementToEncrypt, X509Certificate2 Cert)
{
// Check the arguments.
if (Doc == null)
throw new ArgumentNullException("Doc");
if (ElementToEncrypt == null)
throw new ArgumentNullException("ElementToEncrypt");
if (Cert == null)
throw new ArgumentNullException("Cert");
////////////////////////////////////////////////
// Find the specified element in the XmlDocument
// object and create a new XmlElemnt object.
////////////////////////////////////////////////
XmlElement elementToEncrypt = Doc.GetElementsByTagName(ElementToEncrypt)[0] as XmlElement;
// Throw an XmlException if the element was not found.
if (elementToEncrypt == null)
{
throw new XmlException("The specified element was not found");
}
//////////////////////////////////////////////////
// Create a new instance of the EncryptedXml class
// and use it to encrypt the XmlElement with the
// X.509 Certificate.
//////////////////////////////////////////////////
EncryptedXml eXml = new EncryptedXml();
// Encrypt the element.
EncryptedData edElement = eXml.Encrypt(elementToEncrypt, Cert);
////////////////////////////////////////////////////
// Replace the element from the original XmlDocument
// object with the EncryptedData element.
////////////////////////////////////////////////////
EncryptedXml.ReplaceElement(elementToEncrypt, edElement, false);
}
}
В этом примере предполагается, что файл с именем "test.xml" существует в том же каталоге, что и скомпилированная программа. Также предполагается, что файл "test.xml" содержит элемент "creditcard". Можно поместить следующий XML-код в файл с именем test.xml и использовать его в данном примере.
<root>
<creditcard>
<number>19834209</number>
<expiry>02/02/2002</expiry>
</creditcard>
</root>
Компиляция кода
Для компиляции этого примера может потребоваться включить ссылку на System.Security.dll.
Включите следующие пространства имен: System.Xml, System.Security.Cryptography и System.Security.Cryptography.Xml.
Безопасность
Сертификат X.509, использованный в данном примере, предназначен только для тестирования. Приложения должны использовать сертификаты X.509, созданные доверенным центром сертификации или сервером сертификации Microsoft Windows.
См. также
Задачи
Практическое руководство. Расшифровка XML-элементов с помощью сертификатов X.509
Ссылки
System.Security.Cryptography.Xml