如何:用非对称密钥对 XML 元素进行解密
更新:2010 年 7 月
可以使用 System.Security.Cryptography.Xml 命名空间中的类对 XML 文档中的元素进行加密和解密。 XML 加密是交换或存储加密的 XML 数据的标准方法,无需担心数据被轻易读取。 有关 XML 加密标准的更多信息,请参见万维网联盟 (W3C) 建议 XML Signature Syntax and Processing(XML 签名语法和处理)。
此过程中的示例对用 如何:用非对称密钥对 XML 元素进行加密 中描述的方法加密的 XML 元素进行解密。 它找到一个 <EncryptedData> 元素,对该元素进行解密,然后用原始纯文本 XML 元素替换该元素。
此示例使用了两个密钥对一个 XML 元素进行解密。 它从密钥容器中检索出先前生成的 RSA 私钥,然后用该 RSA 密钥对存储在 <EncryptedData> 元素的 <EncryptedKey> 元素中的会话密钥进行解密。 然后该示例使用该会话密钥对 XML 元素进行解密。
此示例适合于以下情形:多个应用程序必须共享加密数据,或者一个应用程序必须在多次运行之间保存加密数据。
用非对称密钥对 XML 元素进行解密
创建 CspParameters 对象,并指定密钥容器的名称。
Dim cspParams As New CspParameters() cspParams.KeyContainerName = "XML_ENC_RSA_KEY"
CspParameters cspParams = new CspParameters(); cspParams.KeyContainerName = "XML_ENC_RSA_KEY";
使用 RSACryptoServiceProvider 对象从容器中检索先前生成的非对称密钥。 当您将 CspParameters 对象传递给 RSACryptoServiceProvider 构造函数时,将自动从密钥容器中检索该密钥。
Dim rsaKey As New RSACryptoServiceProvider(cspParams)
RSACryptoServiceProvider rsaKey = new RSACryptoServiceProvider(cspParams);
创建新的 EncryptedXml 对象以对文档进行解密。
' Create a new EncryptedXml object. Dim exml As New EncryptedXml(Doc)
// Create a new EncryptedXml object. EncryptedXml exml = 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");
示例
Imports System
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.
If Doc Is Nothing Then
Throw New ArgumentNullException("Doc")
End If
If Alg Is Nothing Then
Throw New ArgumentNullException("Alg")
End If
If KeyName Is Nothing Then
Throw New ArgumentNullException("KeyName")
End If
' 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
using System;
using System.Xml;
using System.Security.Cryptography;
using System.Security.Cryptography.Xml;
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();
}
}
此示例假定一个名为 test.xml 的文件与编译的程序在同一目录中。 它还假定 test.xml 包含使用 如何:用非对称密钥对 XML 元素进行加密 中描述的技术加密的 XML 元素。
编译代码
若要编译此示例,您需要包括对 System.Security.dll 的引用。
包括以下命名空间:System.Xml、System.Security.Cryptography 和 System.Security.Cryptography.Xml。
安全性
不要以纯文本格式存储对称加密密钥,也不要用纯文本在计算机之间传输对称密钥。 另外,不要用纯文本存储或传输非对称密钥对的私钥。 有关对称和非对称加密密钥的更多信息,请参见 生成加密和解密的密钥。
不要将密钥直接嵌入到源代码中。 通过使用 Ildasm.exe(MSIL 反汇编程序),或在记事本等文本编辑器中打开程序集,可以从此程序集轻松读取嵌入的密钥。
加密密钥使用完以后,请通过将每个字节设置为零,或通过调用托管密码类的 Clear 方法,将它从内存中清除。 加密密钥有时可以被调试器从内存读取或从硬盘读取(如果内存位置被分页到磁盘)。
请参见
任务
参考
System.Security.Cryptography.Xml
其他资源
修订记录
日期 |
修订记录 |
原因 |
---|---|---|
2010 年 7 月 |
纠正了顺序混乱的示例。 |
客户反馈 |