Procedura: crittografare gli elementi XML con chiavi simmetriche
Aggiornamento: novembre 2007
È possibile utilizzare le classi dello spazio dei nomi System.Security.Cryptography.Xml per crittografare un elemento all'interno di un documento XML. La crittografia XML consente di memorizzare o trasportare dati XML riservati garantendo un'adeguata protezione da letture non autorizzate. In questa procedura un elemento XML viene decrittografato mediante l'algoritmo AES (Advanced Encryption Standard), noto anche come Rijndael.
Per informazioni su come decrittografare un elemento XML crittografato mediante questa procedura, vedere Procedura: decrittografare gli elementi XML con chiavi simmetriche.
Quando si utilizza un algoritmo simmetrico come AES per crittografare dati XML, è necessario utilizzare la stessa chiave sia per la crittografia che per la decrittografia. Nell'esempio riportato in questa procedura si presuppone che i dati XML verranno decrittografati mediante la stessa chiave e che gli autori della crittografia e della decrittografia abbiano concordato l'algoritmo e la chiave da utilizzare. In questo caso la chiave AES non viene memorizzata né crittografata all'interno dei dati XML crittografati.
L'esempio si riferisce alle situazioni in cui una singola applicazione deve crittografare i dati in base a una chiave sessione memorizzata o a una chiave a crittografia avanzata derivata da una password. Nelle situazioni in cui due o più applicazioni devono condividere dati XML crittografati, è consigliabile utilizzare uno schema di crittografia basato su un algoritmo asimmetrico o un certificato X.509.
Per crittografare un elemento XML con una chiave simmetrica
Generare una chiave simmetrica utilizzando la classe RijndaelManaged. La chiave verrà quindi utilizzata per crittografare l'elemento 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();
Creare un oggetto XmlDocument caricando un file XML dal disco. L'oggetto XmlDocument contiene l'elemento XML da crittografare.
' 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");
Trovare l'elemento specificato nell'oggetto XmlDocument e creare un nuovo oggetto XmlElement per rappresentare l'elemento da crittografare. In questo esempio viene crittografato l'elemento "creditcard".
Dim elementToEncrypt As XmlElement = Doc.GetElementsByTagName(ElementName)(0)
XmlElement elementToEncrypt = Doc.GetElementsByTagName(ElementName)[0] as XmlElement;
Creare una nuova istanza della classe EncryptedXml e utilizzarla per crittografare XmlElement con la chiave simmetrica. Il metodo EncryptData restituisce l'elemento crittografato come una matrice di byte crittografati.
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);
Costruire un oggetto EncryptedData e inserire al suo interno l'identificatore URL dell'elemento della crittografia XML. Tale identificatore indica a coloro che effettueranno la decrittografia che i dati XML contengono un elemento crittografato. È possibile utilizzare il campo XmlEncElementUrl per specificare l'identificatore URL.
Dim edElement As New EncryptedData() edElement.Type = EncryptedXml.XmlEncElementUrl
EncryptedData edElement = new EncryptedData(); edElement.Type = EncryptedXml.XmlEncElementUrl;
Creare un oggetto EncryptionMethod inizializzato sull'identificatore URL dell'algoritmo di crittografia utilizzato per generare la chiave. Passare l'oggetto EncryptionMethod alla proprietà 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);
Aggiungere i dati dell'elemento crittografato all'oggetto EncryptedData.
edElement.CipherData.CipherValue = encryptedElement
edElement.CipherData.CipherValue = encryptedElement;
Sostituire l'elemento dell'oggetto XmlDocument originale con l'elemento EncryptedData.
EncryptedXml.ReplaceElement(elementToEncrypt, edElement, False)
EncryptedXml.ReplaceElement(elementToEncrypt, edElement, false);
Esempio
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);
}
}
}
In questo esempio si presuppone che un file denominato "test.xml" si trovi nella stessa directory del programma compilato e che contenga un elemento "creditcard". È possibile inserire i dati XML riportati di seguito in un file denominato test.xml e utilizzarlo con questo esempio.
<root>
<creditcard>
<number>19834209</number>
<expiry>02/02/2002</expiry>
</creditcard>
</root>
Compilazione del codice
Per compilare l'esempio, è necessario includere un riferimento a System.Security.dll.
Includere gli spazi dei nomi seguenti: System.Xml, System.Security.Cryptography e System.Security.Cryptography.Xml.
Sicurezza
Non memorizzare mai una chiave di crittografia né trasferire una chiave da un computer all'altro in testo non crittografato. Utilizzare piuttosto un contenitore di chiavi protetto per memorizzare le chiavi di crittografia.
Dopo aver utilizzato una chiave di crittografia, cancellarla dalla memoria impostando ogni byte su zero o chiamando il metodo Clear della classe di crittografia gestita.
Vedere anche
Attività
Procedura: decrittografare gli elementi XML con chiavi simmetriche
Riferimenti
System.Security.Cryptography.Xml