方法: 非対称キーで XML 要素を復号化する

System.Security.Cryptography.Xml 名前空間のクラスを使用して、XML ドキュメント内の要素を暗号化および復号化することができます。 XML 暗号化は、データが簡単に読み取られる心配なく、暗号化された XML データを交換または保存する標準的な方法です。 XML 暗号化基準の詳細については、World Wide Web コンソーシアム (W3C) のレコメンデーション「XML 署名の構文と処理」を参照してください。

注意

この記事のコードは Windows に適用されます。

この手順の例では、「方法: 非対称キーで XML 要素を暗号化する」に記載する方法を使用して暗号化された XML 要素を復号化しています。 <EncryptedData> 要素を検出し、要素を復号化してから、要素を元のプレーン テキストの XML 要素に置き換えます。

この例では、2 つのキーを使用して XML 要素を復号化します。 以前に生成された RSA プライベート キーをキー コンテナーから取得します。次に、RSA キーを使用して <EncryptedData> 要素の <EncryptedKey> 要素に格納されているセッション キーを復号化します。 例では、セッション キーを使用して XML 要素を復号化します。

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

非対称キーで 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. <EncryptedData> 要素を復号化するには、DecryptDocument メソッドを呼び出します。 このメソッドは、RSA キーを使用してセッション キーを復号化してから、自動的にセッション キーを使用して、XML 要素を復号化します。 また、<EncryptedData> 要素を元のプレーン テキストに自動的に置き換えます。

    exml.DecryptDocument();
    
    exml.DecryptDocument()
    
  6. XML ドキュメントを保存します。

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

この例では、test.xml という名前のファイルがコンパイル済みのプログラムと同じディレクトリに存在することを前提としています。 さらに、「方法: 非対称キーで XML 要素を暗号化する」に記載する方法を使用して暗号化された XML 要素が test.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 逆アセンブラー) を使用するか、メモ帳などのテキスト エディターでアセンブリを開くと、アセンブリから簡単に読み取ることができます。

暗号化キーを使用して完了したら、各バイトをゼロ (0) にするか、マネージド暗号化クラスの Clear メソッドを呼び出してメモリから消去します。 暗号化キーは、デバッガーによってメモリから読み取られるか、メモリの位置がディスクにページングされている場合はハード ドライブから読み取られることがあります。

関連項目