可以使用 System.Security.Cryptography.Xml 命名空间中的类加密 XML 文档内的元素。 XML 加密可用于存储或传输敏感 XML,而无需担心数据被轻易读取。 此过程使用高级加密标准 (AES) 算法对 XML 元素进行加密。
有关如何解密使用此过程加密的 XML 元素的信息,请参阅如何:用对称密钥解密 XML 元素。
当使用对称算法(如 AES)来加密 XML 数据时,必须使用相同的密钥来加密和解密 XML 数据。 此过程中的示例假定加密的 XML 将使用相同的密钥进行解密,且加密方和解密方就要使用的算法和密钥达成了一致。 此示例不对加密的 XML 内的 AES 密钥进行存储或加密。
此示例适用于以下情况:单个应用程序需要根据内存中存储的会话密钥加密数据,或根据从密码派生而来的加密型强密钥进行加密。 对于两个或多个应用程序需要共享加密的 XML 数据的情况,请考虑使用基于非对称算法或 X.509 证书的加密方案。
使用对称密钥加密 XML 元素
使用 Aes 类生成对称密钥。 此密钥将用于加密 XML 元素。
Aes? key = null; try { // Create a new AES key. key = Aes.Create();
Dim key As Aes = Nothing Try ' Create a new Aes key. key = Aes.Create()
通过从磁盘加载 XML 文件来创建 XmlDocument 对象。 XmlDocument 对象包含要加密的 XML 元素。
// Load an XML document. XmlDocument xmlDoc = new() { PreserveWhitespace = true }; xmlDoc.Load("test.xml");
' Load an XML document. Dim xmlDoc As New XmlDocument() xmlDoc.PreserveWhitespace = True xmlDoc.Load("test.xml")
在 XmlDocument 对象中查找指定元素,并创建一个新的 XmlElement 对象来表示想要加密的元素。 在此示例中,加密了
"creditcard"
元素。XmlElement? elementToEncrypt = Doc.GetElementsByTagName(ElementName)[0] as XmlElement;
Dim elementToEncrypt As XmlElement = Doc.GetElementsByTagName(ElementName)(0)
创建 EncryptedXml 类的新实例,并将其与对称密钥一起使用来加密 XmlElement。 EncryptData 方法以加密的字节数组的形式返回加密元素。
EncryptedXml eXml = new(); byte[] encryptedElement = eXml.EncryptData(elementToEncrypt, Key, false);
Dim eXml As New EncryptedXml() Dim encryptedElement As Byte() = eXml.EncryptData(elementToEncrypt, Key, False)
构造一个 EncryptedData 对象并对其填充 XML 加密元素的 URL 标识符。 此 URL 标识符可使解密方知道 XML 包含一个加密元素。 可使用 XmlEncElementUrl 字段来指定 URL 标识符。
EncryptedData edElement = new() { Type = EncryptedXml.XmlEncElementUrl };
Dim edElement As New EncryptedData() edElement.Type = EncryptedXml.XmlEncElementUrl
创建一个 EncryptionMethod 对象,将它初始化为用于生成密钥的加密算法的 URL 标识符。 将 EncryptionMethod 对象传递给 EncryptionMethod 属性。
string? encryptionMethod; if (Key is Aes) { encryptionMethod = EncryptedXml.XmlEncAES256Url; } else { // Throw an exception if the transform is not AES throw new CryptographicException("The specified algorithm is not supported or not recommended for XML Encryption."); } edElement.EncryptionMethod = new EncryptionMethod(encryptionMethod);
Dim encryptionMethod As String = Nothing If TypeOf Key Is Aes Then encryptionMethod = EncryptedXml.XmlEncAES256Url Else ' Throw an exception if the transform is not in the previous categories Throw New CryptographicException("The specified algorithm is not supported or not recommended for XML Encryption.") End If edElement.EncryptionMethod = New EncryptionMethod(encryptionMethod)
将加密的元素数据添加到 EncryptedData 对象。
edElement.CipherData.CipherValue = encryptedElement;
edElement.CipherData.CipherValue = encryptedElement
将原始 XmlDocument 对象中的元素替换为 EncryptedData 元素。
EncryptedXml.ReplaceElement(elementToEncrypt, edElement, false);
EncryptedXml.ReplaceElement(elementToEncrypt, edElement, False)
示例
<root>
<creditcard>
<number>19834209</number>
<expiry>02/02/2002</expiry>
</creditcard>
</root>
using System;
using System.Xml;
using System.Security.Cryptography;
using System.Security.Cryptography.Xml;
namespace CSCrypto
{
class Program
{
static void Main(string[] args)
{
Aes? key = null;
try
{
// Create a new AES key.
key = Aes.Create();
// Load an XML document.
XmlDocument xmlDoc = new()
{
PreserveWhitespace = true
};
xmlDoc.Load("test.xml");
// Encrypt the "creditcard" element.
Encrypt(xmlDoc, "creditcard", key);
Console.WriteLine("The element was encrypted");
Console.WriteLine(xmlDoc.InnerXml);
Decrypt(xmlDoc, key);
Console.WriteLine("The element was decrypted");
Console.WriteLine(xmlDoc.InnerXml);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
finally
{
key?.Clear();
}
}
public static void Encrypt(XmlDocument Doc, string ElementName, SymmetricAlgorithm Key)
{
// Check the arguments.
ArgumentNullException.ThrowIfNull(Doc);
ArgumentNullException.ThrowIfNull(ElementName);
ArgumentNullException.ThrowIfNull(Key);
////////////////////////////////////////////////
// Find the specified element in the XmlDocument
// object and create a new XmlElement object.
////////////////////////////////////////////////
XmlElement? elementToEncrypt = Doc.GetElementsByTagName(ElementName)[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
// symmetric key.
//////////////////////////////////////////////////
EncryptedXml eXml = new();
byte[] encryptedElement = eXml.EncryptData(elementToEncrypt, Key, false);
////////////////////////////////////////////////
// Construct an EncryptedData object and populate
// it with the desired encryption information.
////////////////////////////////////////////////
EncryptedData edElement = new()
{
Type = EncryptedXml.XmlEncElementUrl
};
// Create an EncryptionMethod element so that the
// receiver knows which algorithm to use for decryption.
// Determine what kind of algorithm is being used and
// supply the appropriate URL to the EncryptionMethod element.
string? encryptionMethod;
if (Key is Aes)
{
encryptionMethod = EncryptedXml.XmlEncAES256Url;
}
else
{
// Throw an exception if the transform is not AES
throw new CryptographicException("The specified algorithm is not supported or not recommended for XML Encryption.");
}
edElement.EncryptionMethod = new EncryptionMethod(encryptionMethod);
// Add the encrypted element data to the
// EncryptedData object.
edElement.CipherData.CipherValue = encryptedElement;
////////////////////////////////////////////////////
// Replace the element from the original XmlDocument
// object with the EncryptedData element.
////////////////////////////////////////////////////
EncryptedXml.ReplaceElement(elementToEncrypt, edElement, false);
}
public static void Decrypt(XmlDocument Doc, SymmetricAlgorithm Alg)
{
// Check the arguments.
ArgumentNullException.ThrowIfNull(Doc);
ArgumentNullException.ThrowIfNull(Alg);
// Find the EncryptedData element in the XmlDocument.
XmlElement? encryptedElement = Doc.GetElementsByTagName("EncryptedData")[0] as XmlElement;
// If the EncryptedData element was not found, throw an exception.
if (encryptedElement == null)
{
throw new XmlException("The EncryptedData element was not found.");
}
// Create an EncryptedData object and populate it.
EncryptedData edElement = new();
edElement.LoadXml(encryptedElement);
// Create a new EncryptedXml object.
EncryptedXml exml = new();
// Decrypt the element using the symmetric key.
byte[] rgbOutput = exml.DecryptData(edElement, Alg);
// Replace the encryptedData element with the plaintext XML element.
exml.ReplaceData(encryptedElement, rgbOutput);
}
}
}
Imports System.Xml
Imports System.Security.Cryptography
Imports System.Security.Cryptography.Xml
Module Program
Sub Main(ByVal args() As String)
Dim key As Aes = Nothing
Try
' Create a new Aes key.
key = Aes.Create()
' Load an XML document.
Dim xmlDoc As New XmlDocument()
xmlDoc.PreserveWhitespace = True
xmlDoc.Load("test.xml")
' Encrypt the "creditcard" element.
Encrypt(xmlDoc, "creditcard", key)
Console.WriteLine("The element was encrypted")
Console.WriteLine(xmlDoc.InnerXml)
Decrypt(xmlDoc, key)
Console.WriteLine("The element was decrypted")
Console.WriteLine(xmlDoc.InnerXml)
Catch e As Exception
Console.WriteLine(e.Message)
Finally
' Clear the key.
If Not (key Is Nothing) Then
key.Clear()
End If
End Try
End Sub
Sub Encrypt(ByVal Doc As XmlDocument, ByVal ElementName As String, ByVal Key As SymmetricAlgorithm)
' Check the arguments.
ArgumentNullException.ThrowIfNull(Doc)
ArgumentNullException.ThrowIfNull(ElementName)
ArgumentNullException.ThrowIfNull(Key)
''''''''''''''''''''''''''''''''''''''''''''''''''
' Find the specified element in the XmlDocument
' object and create a new XmlElemnt object.
''''''''''''''''''''''''''''''''''''''''''''''''''
Dim elementToEncrypt As XmlElement = Doc.GetElementsByTagName(ElementName)(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
' symmetric key.
''''''''''''''''''''''''''''''''''''''''''''''''''
Dim eXml As New EncryptedXml()
Dim encryptedElement As Byte() = eXml.EncryptData(elementToEncrypt, Key, False)
''''''''''''''''''''''''''''''''''''''''''''''''''
' Construct an EncryptedData object and populate
' it with the desired encryption information.
''''''''''''''''''''''''''''''''''''''''''''''''''
Dim edElement As New EncryptedData()
edElement.Type = EncryptedXml.XmlEncElementUrl
' Create an EncryptionMethod element so that the
' receiver knows which algorithm to use for decryption.
' Determine what kind of algorithm is being used and
' supply the appropriate URL to the EncryptionMethod element.
Dim encryptionMethod As String = Nothing
If TypeOf Key Is Aes Then
encryptionMethod = EncryptedXml.XmlEncAES256Url
Else
' Throw an exception if the transform is not in the previous categories
Throw New CryptographicException("The specified algorithm is not supported or not recommended for XML Encryption.")
End If
edElement.EncryptionMethod = New EncryptionMethod(encryptionMethod)
' Add the encrypted element data to the
' EncryptedData object.
edElement.CipherData.CipherValue = encryptedElement
''''''''''''''''''''''''''''''''''''''''''''''''''
' Replace the element from the original XmlDocument
' object with the EncryptedData element.
''''''''''''''''''''''''''''''''''''''''''''''''''
EncryptedXml.ReplaceElement(elementToEncrypt, edElement, False)
End Sub
Sub Decrypt(ByVal Doc As XmlDocument, ByVal Alg As SymmetricAlgorithm)
' 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
' Find the EncryptedData element in the XmlDocument.
Dim encryptedElement As XmlElement = Doc.GetElementsByTagName("EncryptedData")(0)
' If the EncryptedData element was not found, throw an exception.
If encryptedElement Is Nothing Then
Throw New XmlException("The EncryptedData element was not found.")
End If
' Create an EncryptedData object and populate it.
Dim edElement As New EncryptedData()
edElement.LoadXml(encryptedElement)
' Create a new EncryptedXml object.
Dim exml As New EncryptedXml()
' Decrypt the element using the symmetric key.
Dim rgbOutput As Byte() = exml.DecryptData(edElement, Alg)
' Replace the encryptedData element with the plaintext XML element.
exml.ReplaceData(encryptedElement, rgbOutput)
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 安全性
永远不要以纯文本形式存储加密密钥,也不要以纯文本形式在计算机之间传输密钥。 请转而使用安全的密钥容器来存储加密密钥。
当你使用加密密钥执行操作后,通过将每个字节设置为零或通过调用托管加密类的 Clear 方法来将它从内存中清除。
另请参阅
- 加密模型 - 介绍如何在基类库中实现加密。
- 加密服务
- 跨平台加密
- System.Security.Cryptography.Xml
- 如何:用对称密钥对 XML 元素进行解密
- ASP.NET Core 数据保护