方法 : X.509 証明書で XML 要素を暗号化する

System.Security.Cryptography.Xml 名前空間のクラスを使用して、XML ドキュメント内の要素を暗号化できます。 XML 暗号化は暗号化された XML データを変換または格納する標準の方法で、データを簡単に読み取られるおそれがありません。 XML 暗号化標準の詳細については、http://www.w3.org/TR/xmldsig-core/ の World Wide Web Consortium (W3C) specification for XML Encryption を参照してください。

XML 暗号化を使用して、任意の XML 要素やドキュメントを、暗号化された XML データを含む <EncryptedData> 要素に置き換えることができます。 <EncryptedData> 要素には、暗号化の際に使用されたキーとプロセスに関する情報などのサブ要素も含まれます。 XML 暗号化では、ドキュメントに複数の暗号化された要素を含めたり、要素を複数回暗号化したりできます。 この手順のコード例では、暗号化の間に後で使用できるその他の複数のサブ要素と共に、<EncryptedData> 要素の作成方法を示します。

この例では、2 つのキーを使用して XML 要素を暗号化します。 Makecert.exe (証明書作成ツール) を使用してテスト X.509 証明書を生成し、その証明書を証明書ストアに保存します。 次に、この例では、プログラムによって証明書を取得し、それを使用して Encrypt メソッドにより XML 要素を暗号化します。 内部的には、Encrypt メソッドは個別のセッション キーを作成し、それを使用して XML ドキュメントを暗号化します。 このメソッドはセッション キーを暗号化し、暗号化された XML と共に新しい <EncryptedData> 要素内に保存します。

XML 要素を復号化するには、単に DecryptDocument メソッドを呼び出します。このメソッドは、ストアから X.509 証明書を自動的に取得して、必要な復号化を実行します。 この手順を使用して暗号化された XML 要素を復号化する方法の詳細については、「方法 : X.509 証明書で XML 要素を復号化する」を参照してください。

この例は、複数のアプリケーションが暗号化されたデータを共有する必要がある状況や、1 つのアプリケーションが実行するたびに暗号化されたデータを保存する必要のある状況に適しています。

X.509 証明書で XML 要素を暗号化するには

  1. 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
    
  2. X509Store オブジェクトを作成し、それを初期化して現在のユーザー ストアを開きます。

    Dim store As New X509Store(StoreLocation.CurrentUser)
    
    X509Store store = new X509Store(StoreLocation.CurrentUser);
    
  3. 読み取り専用モードでストアを開きます。

    store.Open(OpenFlags.ReadOnly)
    
    store.Open(OpenFlags.ReadOnly);
    
  4. ストアのすべての証明書を使用して X509Certificate2Collection を初期化します。

    Dim certCollection As X509Certificate2Collection = store.Certificates
    
    X509Certificate2Collection certCollection = store.Certificates;
    
  5. ストア内の証明書を列挙し、適切な名前を持つ証明書を見つけます。 この例では、証明書の名前は "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;
        }
    }
    
  6. 証明書が見つかったら、ストアを閉じます。

    store.Close()
    
    store.Close();
    
  7. ディスクから XML ファイルをロードして、XmlDocument オブジェクトを作成します。 XmlDocument オブジェクトには、暗号化する XML 要素が含まれます。

    Dim xmlDoc As New XmlDocument()
    
    XmlDocument xmlDoc = new XmlDocument();
    
  8. XmlDocument オブジェクトで指定された要素を検索し、新しい XmlElement オブジェクトを作成して暗号化する要素を表します。 この例では、"creditcard" 要素が暗号化されます。

            Dim elementToEncrypt As XmlElement = Doc.GetElementsByTagName(ElementToEncryptName)(0)
    
    
    XmlElement elementToEncrypt = Doc.GetElementsByTagName(ElementToEncrypt)[0] as XmlElement;
    
  9. 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);
    
  10. 元の XmlDocument オブジェクトの要素を EncryptedData 要素に置き換えます。

    EncryptedXml.ReplaceElement(elementToEncrypt, edElement, False)
    
    EncryptedXml.ReplaceElement(elementToEncrypt, edElement, false);
    
  11. 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" 要素が含まれていることも前提としています。 test.xml という名前のファイルに次の XML を配置し、その XML をこの例と共に使用できます。

<root>
    <creditcard>
        <number>19834209</number>
        <expiry>02/02/2002</expiry>
    </creditcard>
</root>

コードのコンパイル

セキュリティ

この例で使用される X.509 証明書は、テストだけを目的としています。 アプリケーションでは、信頼できる証明機関によって生成された X.509 証明書を使用するか、Microsoft Windows Certificate Server によって生成された証明書を使用する必要があります。

参照

処理手順

方法 : X.509 証明書で XML 要素を復号化する

参照

System.Security.Cryptography.Xml

その他の技術情報

XML 暗号化と XML デジタル署名