如何:用对称密钥对 XML 元素进行加密
可以使用 System.Security.Cryptography.Xml 命名空间中的类对 XML 文档中的元素进行加密。 使用 XML 加密,您可以存储或传输敏感 XML,而无需担心数据被轻易读取。 此过程使用高级加密标准 (AES) 算法(又称为 Rijndael)对 XML 元素进行解密。
有关如何对使用此过程加密的 XML 元素进行解密的信息,请参见 如何:用对称密钥对 XML 元素进行解密。
当使用诸如 AES 这样的对称算法对 XML 数据进行加密时,必须使用相同的密钥对 XML 数据进行加密和解密。 此过程中的示例假定加密的 XML 将使用相同密钥进行解密,并且加密方和解密方对使用的算法和密钥达成了一致。 此示例不在加密的 XML 中存储或加密 AES 密钥。
此示例适合于以下情形:单个应用程序需要基于存储在内存中的会话密钥,或基于从密码派生的加密强密钥对数据进行加密。 对于两个或多个应用程序需要共享加密的 XML 数据的情形,请考虑使用基于非对称算法或 X.509 证书的加密方案。
用对称密钥对 XML 元素进行加密
使用 RijndaelManaged 类生成一个对称密钥。 该密钥将被用来对 XML 元素进行加密。
Dim key As RijndaelManaged = Nothing Try ' Create a new Rijndael key. key = New RijndaelManaged()
RijndaelManaged key = null; try { // Create a new Rijndael key. key = new RijndaelManaged();
通过从磁盘加载 XML 文件创建 XmlDocument 对象。 XmlDocument 对象包含要加密的 XML 元素。
' Load an XML document. Dim xmlDoc As New XmlDocument() xmlDoc.PreserveWhitespace = True xmlDoc.Load("test.xml")
// Load an XML document. XmlDocument xmlDoc = new XmlDocument(); xmlDoc.PreserveWhitespace = true; xmlDoc.Load("test.xml");
在 XmlDocument 对象中找到指定的元素,然后创建一个新的 XmlElement 对象来表示要加密的元素。 在此示例中,"creditcard" 元素要加密。
Dim elementToEncrypt As XmlElement = Doc.GetElementsByTagName(ElementName)(0)
XmlElement elementToEncrypt = Doc.GetElementsByTagName(ElementName)[0] as XmlElement;
创建 EncryptedXml 类的新实例,并使用它通过对称密钥对 XmlElement 进行加密。 EncryptData 方法将加密的元素作为加密字节的数组返回。
Dim eXml As New EncryptedXml() Dim encryptedElement As Byte() = eXml.EncryptData(elementToEncrypt, Key, False)
EncryptedXml eXml = new EncryptedXml(); byte[] encryptedElement = eXml.EncryptData(elementToEncrypt, Key, false);
构造一个 EncryptedData 对象,然后用 XML 加密元素的 URL 标识符填充它。 此 URL 标识符使解密方知道 XML 包含一个加密元素。 可以使用 XmlEncElementUrl 字段指定 URL 标识符。
Dim edElement As New EncryptedData() edElement.Type = EncryptedXml.XmlEncElementUrl
EncryptedData edElement = new EncryptedData(); edElement.Type = EncryptedXml.XmlEncElementUrl;
创建 EncryptionMethod 对象,该对象被初始化为用来生成密钥的加密算法的 URL 标识符。 将 EncryptionMethod 对象传递给 EncryptionMethod 属性。
Dim encryptionMethod As String = Nothing If TypeOf Key Is TripleDES Then encryptionMethod = EncryptedXml.XmlEncTripleDESUrl ElseIf TypeOf Key Is DES Then encryptionMethod = EncryptedXml.XmlEncDESUrl End If If TypeOf Key Is Rijndael Then Select Case Key.KeySize Case 128 encryptionMethod = EncryptedXml.XmlEncAES128Url Case 192 encryptionMethod = EncryptedXml.XmlEncAES192Url Case 256 encryptionMethod = EncryptedXml.XmlEncAES256Url End Select Else ' Throw an exception if the transform is not in the previous categories Throw New CryptographicException("The specified algorithm is not supported for XML Encryption.") End If edElement.EncryptionMethod = New EncryptionMethod(encryptionMethod)
string encryptionMethod = null; if (Key is TripleDES) { encryptionMethod = EncryptedXml.XmlEncTripleDESUrl; } else if (Key is DES) { encryptionMethod = EncryptedXml.XmlEncDESUrl; } if (Key is Rijndael) { switch (Key.KeySize) { case 128: encryptionMethod = EncryptedXml.XmlEncAES128Url; break; case 192: encryptionMethod = EncryptedXml.XmlEncAES192Url; break; case 256: encryptionMethod = EncryptedXml.XmlEncAES256Url; break; } } else { // Throw an exception if the transform is not in the previous categories throw new CryptographicException("The specified algorithm is not supported for XML Encryption."); } edElement.EncryptionMethod = new EncryptionMethod(encryptionMethod);
将加密的元素数据添加到 EncryptedData 对象中。
edElement.CipherData.CipherValue = encryptedElement
edElement.CipherData.CipherValue = encryptedElement;
用 EncryptedData 元素替换原始 XmlDocument 对象中的元素。
EncryptedXml.ReplaceElement(elementToEncrypt, edElement, False)
EncryptedXml.ReplaceElement(elementToEncrypt, edElement, false);
示例
Imports System
Imports System.Xml
Imports System.Security.Cryptography
Imports System.Security.Cryptography.Xml
Module Program
Sub Main(ByVal args() As String)
Dim key As RijndaelManaged = Nothing
Try
' Create a new Rijndael key.
key = New RijndaelManaged()
' 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.
If Doc Is Nothing Then
Throw New ArgumentNullException("Doc")
End If
If ElementName Is Nothing Then
Throw New ArgumentNullException("ElementToEncrypt")
End If
If Key Is Nothing Then
Throw New ArgumentNullException("Alg")
End If
''''''''''''''''''''''''''''''''''''''''''''''''''
' 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 TripleDES Then
encryptionMethod = EncryptedXml.XmlEncTripleDESUrl
ElseIf TypeOf Key Is DES Then
encryptionMethod = EncryptedXml.XmlEncDESUrl
End If
If TypeOf Key Is Rijndael Then
Select Case Key.KeySize
Case 128
encryptionMethod = EncryptedXml.XmlEncAES128Url
Case 192
encryptionMethod = EncryptedXml.XmlEncAES192Url
Case 256
encryptionMethod = EncryptedXml.XmlEncAES256Url
End Select
Else
' Throw an exception if the transform is not in the previous categories
Throw New CryptographicException("The specified algorithm is not supported 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 'Encrypt
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
using System;
using System.Xml;
using System.Security.Cryptography;
using System.Security.Cryptography.Xml;
namespace CSCrypto
{
class Program
{
static void Main(string[] args)
{
RijndaelManaged key = null;
try
{
// Create a new Rijndael key.
key = new RijndaelManaged();
// Load an XML document.
XmlDocument xmlDoc = 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 (Exception e)
{
Console.WriteLine(e.Message);
}
finally
{
// Clear the key.
if (key != null)
{
key.Clear();
}
}
}
public static void Encrypt(XmlDocument Doc, string ElementName, SymmetricAlgorithm Key)
{
// Check the arguments.
if (Doc == null)
throw new ArgumentNullException("Doc");
if (ElementName == null)
throw new ArgumentNullException("ElementToEncrypt");
if (Key == null)
throw new ArgumentNullException("Alg");
////////////////////////////////////////////////
// Find the specified element in the XmlDocument
// object and create a new XmlElemnt 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 EncryptedXml();
byte[] encryptedElement = eXml.EncryptData(elementToEncrypt, Key, false);
////////////////////////////////////////////////
// Construct an EncryptedData object and populate
// it with the desired encryption information.
////////////////////////////////////////////////
EncryptedData edElement = 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.
string encryptionMethod = null;
if (Key is TripleDES)
{
encryptionMethod = EncryptedXml.XmlEncTripleDESUrl;
}
else if (Key is DES)
{
encryptionMethod = EncryptedXml.XmlEncDESUrl;
}
if (Key is Rijndael)
{
switch (Key.KeySize)
{
case 128:
encryptionMethod = EncryptedXml.XmlEncAES128Url;
break;
case 192:
encryptionMethod = EncryptedXml.XmlEncAES192Url;
break;
case 256:
encryptionMethod = EncryptedXml.XmlEncAES256Url;
break;
}
}
else
{
// Throw an exception if the transform is not in the previous categories
throw new CryptographicException("The specified algorithm is not supported 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.
if (Doc == null)
throw new ArgumentNullException("Doc");
if (Alg == null)
throw new ArgumentNullException("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 EncryptedData();
edElement.LoadXml(encryptedElement);
// Create a new EncryptedXml object.
EncryptedXml exml = new EncryptedXml();
// 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);
}
}
}
此示例假定一个名为 "test.xml" 的文件与编译的程序在同一目录中。 它还假定 "test.xml" 包含一个 "creditcard" 元素。 您可以将以下 XML 放入名为 test.xml 的文件中,并将它和此示例一起使用。
<root>
<creditcard>
<number>19834209</number>
<expiry>02/02/2002</expiry>
</creditcard>
</root>
编译代码
若要编译此示例,您需要包括对 System.Security.dll 的引用。
包括以下命名空间:System.Xml、System.Security.Cryptography 和 System.Security.Cryptography.Xml。
安全性
不要以纯文本格式存储加密密钥,也不要用纯文本在计算机之间传输密钥。 请转而使用安全密钥容器存储加密密钥。
加密密钥使用完以后,请通过将每个字节设置为零,或通过调用托管密码类的 Clear 方法,将它从内存中清除。
请参见
任务
参考
System.Security.Cryptography.Xml