如何:用非对称密钥对 XML 元素进行解密
可以使用 System.Security.Cryptography.Xml 命名空间中的类对 XML 文档内的元素进行加密和解密。 XML 加密是交换或存储加密的 XML 数据的一种标准方式,使用后就无需担心数据被轻易读取。 有关 XML 加密标准的详细信息,请参阅万维网联盟 (W3C) 建议 XML 签名语法和处理。
注意
本文中的代码适用于 Windows。
此步骤中的示例对使用如何:用非对称密钥对 XML 元素进行加密中描述的方法进行加密的 XML 元素进行解密。 它找到一个 <EncryptedData
> 元素,解密该元素,然后将其替换为原始纯文本 XML 元素。
此示例使用两个密钥对 XML 元素进行解密。 它从密钥容器中检索以前生成的 RSA 私钥,然后使用 RSA 密钥解密存储在 <EncryptedData
> 元素的 <EncryptedKey
> 元素中的会话密钥。 然后此示例使用会话密钥对 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 反汇编程序) 或在文本编辑器(如记事本)中打开程序集的方式从程序集中轻松读取嵌入的密钥。
当你使用加密密钥执行操作后,通过将每个字节设置为零或通过调用托管加密类的 Clear 方法来将它从内存中清除。 加密密钥有时可从内存由调试器读取,或从硬盘读取(如果内存位置分页到磁盘)。