Kommentar
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Du kan använda klasserna i System.Security.Cryptography.Xml namnområdet för att kryptera ett element i ett XML-dokument. XML-kryptering är ett standard sätt att utbyta eller lagra krypterade XML-data, utan att behöva oroa dig för att data ska läsas enkelt. Mer information om XML-krypteringsstandarden finns i W3C-specifikationen (World Wide Web Consortium) för XML-kryptering på https://www.w3.org/TR/xmldsig-core/.
Du kan använda XML-kryptering för att ersätta alla XML-element eller dokument med ett <EncryptedData> element som innehåller krypterade XML-data. Elementet <EncryptedData> kan också innehålla underelement som innehåller information om de nycklar och processer som används under krypteringen. MED XML-kryptering kan ett dokument innehålla flera krypterade element och ett element kan krypteras flera gånger. Kodexemplet i den här proceduren visar hur du skapar ett <EncryptedData> element tillsammans med flera andra underelement som du kan använda senare under dekrypteringen.
I det här exemplet krypteras ett XML-element med två nycklar. Den genererar ett offentligt/privat RSA-nyckelpar och sparar nyckelparet i en säker nyckelcontainer. Exemplet skapar sedan en separat sessionsnyckel med hjälp av AES-algoritmen (Advanced Encryption Standard). I exemplet används AES-sessionsnyckeln för att kryptera XML-dokumentet och använder sedan den offentliga RSA-nyckeln för att kryptera AES-sessionsnyckeln. Slutligen sparar exemplet den krypterade AES-sessionsnyckeln och krypterade XML-data i XML-dokumentet i ett nytt <EncryptedData> element.
Om du vill dekryptera XML-elementet hämtar du den privata RSA-nyckeln från nyckelcontainern, använder den för att dekryptera sessionsnyckeln och använder sedan sessionsnyckeln för att dekryptera dokumentet. Mer information om hur du dekrypterar ett XML-element som krypterades med den här proceduren finns i Så här dekrypterar du XML-element med asymmetriska nycklar.
Det här exemplet är lämpligt för situationer där flera program behöver dela krypterade data eller där ett program behöver spara krypterade data mellan de gånger det körs.
Så här krypterar du ett XML-element med en asymmetrisk nyckel
Skapa ett CspParameters objekt och ange namnet på nyckelcontainern.
CspParameters cspParams = new CspParameters(); cspParams.KeyContainerName = "XML_ENC_RSA_KEY";Dim cspParams As New CspParameters() cspParams.KeyContainerName = "XML_ENC_RSA_KEY"Generera en asymmetrisk nyckel med hjälp av RSACryptoServiceProvider klassen . Nyckeln sparas automatiskt i nyckelcontainern när du skickar CspParameters objektet till klassens RSACryptoServiceProvider konstruktor. Den här nyckeln används för att kryptera AES-sessionsnyckeln och kan hämtas senare för att dekryptera den.
RSACryptoServiceProvider rsaKey = new RSACryptoServiceProvider(cspParams);Dim rsaKey As New RSACryptoServiceProvider(cspParams)Skapa ett XmlDocument objekt genom att läsa in en XML-fil från disken. Objektet XmlDocument innehåller XML-elementet som ska krypteras.
// 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); }' 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 TryLeta upp det angivna elementet XmlDocument i objektet och skapa ett nytt XmlElement objekt som representerar det element som du vill kryptera. I det här exemplet krypteras elementet
"creditcard".XmlElement? elementToEncrypt = Doc.GetElementsByTagName(ElementToEncrypt)[0] as XmlElement; // Throw an XmlException if the element was not found. if (elementToEncrypt == null) { throw new XmlException("The specified element was not found"); }Dim elementToEncrypt As XmlElement = Doc.GetElementsByTagName(EncryptionElement)(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 IfSkapa en ny sessionsnyckel med hjälp av Aes klassen . Den här nyckeln krypterar XML-elementet och krypteras sedan självt och placeras i XML-dokumentet.
// Create an AES key. sessionKey = Aes.Create();' Create an AES key. sessionKey = Aes.Create()Skapa en ny instans av klassen och använd den för att kryptera det angivna elementet med hjälp av EncryptedXml sessionsnyckeln. Metoden EncryptData returnerar det krypterade elementet som en matris med krypterade byte.
EncryptedXml eXml = new EncryptedXml(); byte[] encryptedElement = eXml.EncryptData(elementToEncrypt, sessionKey, false);Dim eXml As New EncryptedXml() Dim encryptedElement As Byte() = eXml.EncryptData(elementToEncrypt, sessionKey, False)Konstruera ett EncryptedData objekt och fyll i det med URL-identifieraren för det krypterade XML-elementet. Med den här URL-identifieraren kan en dekrypteringspart veta att XML:en innehåller ett krypterat element. Du kan använda fältet XmlEncElementUrl för att ange URL-identifieraren. XML-elementet i klartext ersätts av ett
<EncryptedData>element som kapslas in av det här EncryptedData objektet.EncryptedData edElement = new EncryptedData(); edElement.Type = EncryptedXml.XmlEncElementUrl; edElement.Id = EncryptionElementID;Dim edElement As New EncryptedData() edElement.Type = EncryptedXml.XmlEncElementUrl edElement.Id = EncryptionElementIDSkapa ett EncryptionMethod objekt som initieras till URL-identifieraren för den kryptografiska algoritm som används för att generera sessionsnyckeln. Skicka objektet EncryptionMethod till egenskapen EncryptionMethod .
edElement.EncryptionMethod = new EncryptionMethod(EncryptedXml.XmlEncAES256Url);edElement.EncryptionMethod = New EncryptionMethod(EncryptedXml.XmlEncAES256Url)Skapa ett EncryptedKey objekt som ska innehålla den krypterade sessionsnyckeln. Kryptera sessionsnyckeln, lägg till den i EncryptedKey objektet och ange ett sessionsnyckelnamn och en url för nyckelidentifieraren.
EncryptedKey ek = new EncryptedKey(); byte[] encryptedKey = EncryptedXml.EncryptKey(sessionKey.Key, Alg, false); ek.CipherData = new CipherData(encryptedKey); ek.EncryptionMethod = new EncryptionMethod(EncryptedXml.XmlEncRSA15Url);Dim ek As New EncryptedKey() Dim encryptedKey As Byte() = EncryptedXml.EncryptKey(sessionKey.Key, Alg, False) ek.CipherData = New CipherData(encryptedKey) ek.EncryptionMethod = New EncryptionMethod(EncryptedXml.XmlEncRSA15Url)Skapa ett nytt DataReference objekt som mappar krypterade data till en viss sessionsnyckel. Med det här valfria steget kan du enkelt ange att flera delar av ett XML-dokument har krypterats med en enda nyckel.
DataReference dRef = new DataReference(); // Specify the EncryptedData URI. dRef.Uri = "#" + EncryptionElementID; // Add the DataReference to the EncryptedKey. ek.AddReference(dRef);Dim dRef As New DataReference() ' Specify the EncryptedData URI. dRef.Uri = "#" + EncryptionElementID ' Add the DataReference to the EncryptedKey. ek.AddReference(dRef)Lägg till den krypterade nyckeln i EncryptedData objektet.
edElement.KeyInfo.AddClause(new KeyInfoEncryptedKey(ek));edElement.KeyInfo.AddClause(New KeyInfoEncryptedKey(ek))Skapa ett nytt KeyInfo objekt för att ange namnet på RSA-nyckeln. Lägg till den i EncryptedData objektet. Detta hjälper dekrypteringsparten att identifiera rätt asymmetrisk nyckel som ska användas vid dekryptering av sessionsnyckeln.
// Create a new KeyInfoName element. KeyInfoName kin = new KeyInfoName(); // Specify a name for the key. kin.Value = KeyName; // Add the KeyInfoName element to the // EncryptedKey object. ek.KeyInfo.AddClause(kin);' Create a new KeyInfoName element. Dim kin As New KeyInfoName() ' Specify a name for the key. kin.Value = KeyName ' Add the KeyInfoName element to the ' EncryptedKey object. ek.KeyInfo.AddClause(kin)Lägg till krypterade elementdata i EncryptedData objektet.
edElement.CipherData.CipherValue = encryptedElement;edElement.CipherData.CipherValue = encryptedElementErsätt elementet från det ursprungliga XmlDocument objektet med elementet EncryptedData .
EncryptedXml.ReplaceElement(elementToEncrypt, edElement, false);EncryptedXml.ReplaceElement(elementToEncrypt, edElement, False)Spara objektet XmlDocument .
xmlDoc.Save("test.xml");xmlDoc.Save("test.xml")
Exempel
Det här exemplet förutsätter att en fil med namnet "test.xml" finns i samma katalog som det kompilerade programmet. Det förutsätter också att det "test.xml" innehåller ett "creditcard" element. Du kan placera följande XML i en fil som heter test.xml och använda den med det här exemplet.
<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;
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);
}
// Create a new CspParameters object to specify
// a key container.
CspParameters cspParams = new CspParameters();
cspParams.KeyContainerName = "XML_ENC_RSA_KEY";
// Create a new RSA key and save it in the container. This key will encrypt
// a symmetric key, which will then be encrypted in the XML document.
RSACryptoServiceProvider rsaKey = new RSACryptoServiceProvider(cspParams);
try
{
// Encrypt the "creditcard" element.
Encrypt(xmlDoc, "creditcard", "EncryptedElement1", rsaKey, "rsaKey");
// Save the XML document.
xmlDoc.Save("test.xml");
// Display the encrypted XML to the console.
Console.WriteLine("Encrypted XML:");
Console.WriteLine();
Console.WriteLine(xmlDoc.OuterXml);
Decrypt(xmlDoc, rsaKey, "rsaKey");
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 Encrypt(XmlDocument Doc, string ElementToEncrypt, string EncryptionElementID, RSA Alg, string KeyName)
{
// Check the arguments.
if (Doc == null)
throw new ArgumentNullException("Doc");
if (ElementToEncrypt == null)
throw new ArgumentNullException("ElementToEncrypt");
if (EncryptionElementID == null)
throw new ArgumentNullException("EncryptionElementID");
if (Alg == null)
throw new ArgumentNullException("Alg");
if (KeyName == null)
throw new ArgumentNullException("KeyName");
////////////////////////////////////////////////
// Find the specified element in the XmlDocument
// object and create a new XmlElement object.
////////////////////////////////////////////////
XmlElement? elementToEncrypt = Doc.GetElementsByTagName(ElementToEncrypt)[0] as XmlElement;
// Throw an XmlException if the element was not found.
if (elementToEncrypt == null)
{
throw new XmlException("The specified element was not found");
}
Aes? sessionKey = null;
try
{
//////////////////////////////////////////////////
// Create a new instance of the EncryptedXml class
// and use it to encrypt the XmlElement with the
// a new random symmetric key.
//////////////////////////////////////////////////
// Create an AES key.
sessionKey = Aes.Create();
EncryptedXml eXml = new EncryptedXml();
byte[] encryptedElement = eXml.EncryptData(elementToEncrypt, sessionKey, false);
////////////////////////////////////////////////
// Construct an EncryptedData object and populate
// it with the desired encryption information.
////////////////////////////////////////////////
EncryptedData edElement = new EncryptedData();
edElement.Type = EncryptedXml.XmlEncElementUrl;
edElement.Id = EncryptionElementID;
// Create an EncryptionMethod element so that the
// receiver knows which algorithm to use for decryption.
edElement.EncryptionMethod = new EncryptionMethod(EncryptedXml.XmlEncAES256Url);
// Encrypt the session key and add it to an EncryptedKey element.
EncryptedKey ek = new EncryptedKey();
byte[] encryptedKey = EncryptedXml.EncryptKey(sessionKey.Key, Alg, false);
ek.CipherData = new CipherData(encryptedKey);
ek.EncryptionMethod = new EncryptionMethod(EncryptedXml.XmlEncRSA15Url);
// Create a new DataReference element
// for the KeyInfo element. This optional
// element specifies which EncryptedData
// uses this key. An XML document can have
// multiple EncryptedData elements that use
// different keys.
DataReference dRef = new DataReference();
// Specify the EncryptedData URI.
dRef.Uri = "#" + EncryptionElementID;
// Add the DataReference to the EncryptedKey.
ek.AddReference(dRef);
// Add the encrypted key to the
// EncryptedData object.
edElement.KeyInfo.AddClause(new KeyInfoEncryptedKey(ek));
// Set the KeyInfo element to specify the
// name of the RSA key.
// Create a new KeyInfoName element.
KeyInfoName kin = new KeyInfoName();
// Specify a name for the key.
kin.Value = KeyName;
// Add the KeyInfoName element to the
// EncryptedKey object.
ek.KeyInfo.AddClause(kin);
// 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);
}
finally
{
sessionKey?.Clear();
}
}
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
Class Program
Shared 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
' Create a new CspParameters object to specify
' a key container.
Dim cspParams As New CspParameters()
cspParams.KeyContainerName = "XML_ENC_RSA_KEY"
' Create a new RSA key and save it in the container. This key will encrypt
' a symmetric key, which will then be encrypted in the XML document.
Dim rsaKey As New RSACryptoServiceProvider(cspParams)
Try
' Encrypt the "creditcard" element.
Encrypt(xmlDoc, "creditcard", "EncryptedElement1", rsaKey, "rsaKey")
' Save the XML document.
xmlDoc.Save("test.xml")
' Display the encrypted XML to the console.
Console.WriteLine("Encrypted XML:")
Console.WriteLine()
Console.WriteLine(xmlDoc.OuterXml)
Decrypt(xmlDoc, rsaKey, "rsaKey")
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
Public Shared Sub Encrypt(ByVal Doc As XmlDocument, ByVal EncryptionElement As String, ByVal EncryptionElementID As String, ByVal Alg As RSA, ByVal KeyName As String)
' Check the arguments.
ArgumentNullException.ThrowIfNull(Doc)
ArgumentNullException.ThrowIfNull(EncryptionElement)
ArgumentNullException.ThrowIfNull(EncryptionElementID)
ArgumentNullException.ThrowIfNull(Alg)
ArgumentNullException.ThrowIfNull(KeyName)
'//////////////////////////////////////////////
' Find the specified element in the XmlDocument
' object and create a new XmlElement object.
'//////////////////////////////////////////////
Dim elementToEncrypt As XmlElement = Doc.GetElementsByTagName(EncryptionElement)(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
Dim sessionKey As Aes = Nothing
Try
'////////////////////////////////////////////////
' Create a new instance of the EncryptedXml class
' and use it to encrypt the XmlElement with the
' a new random symmetric key.
'////////////////////////////////////////////////
' Create an AES key.
sessionKey = Aes.Create()
Dim eXml As New EncryptedXml()
Dim encryptedElement As Byte() = eXml.EncryptData(elementToEncrypt, sessionKey, False)
'//////////////////////////////////////////////
' Construct an EncryptedData object and populate
' it with the desired encryption information.
'//////////////////////////////////////////////
Dim edElement As New EncryptedData()
edElement.Type = EncryptedXml.XmlEncElementUrl
edElement.Id = EncryptionElementID
' Create an EncryptionMethod element so that the
' receiver knows which algorithm to use for decryption.
edElement.EncryptionMethod = New EncryptionMethod(EncryptedXml.XmlEncAES256Url)
' Encrypt the session key and add it to an EncryptedKey element.
Dim ek As New EncryptedKey()
Dim encryptedKey As Byte() = EncryptedXml.EncryptKey(sessionKey.Key, Alg, False)
ek.CipherData = New CipherData(encryptedKey)
ek.EncryptionMethod = New EncryptionMethod(EncryptedXml.XmlEncRSA15Url)
' Create a new DataReference element
' for the KeyInfo element. This optional
' element specifies which EncryptedData
' uses this key. An XML document can have
' multiple EncryptedData elements that use
' different keys.
Dim dRef As New DataReference()
' Specify the EncryptedData URI.
dRef.Uri = "#" + EncryptionElementID
' Add the DataReference to the EncryptedKey.
ek.AddReference(dRef)
' Add the encrypted key to the
' EncryptedData object.
edElement.KeyInfo.AddClause(New KeyInfoEncryptedKey(ek))
' Set the KeyInfo element to specify the
' name of the RSA key.
' Create a new KeyInfoName element.
Dim kin As New KeyInfoName()
' Specify a name for the key.
kin.Value = KeyName
' Add the KeyInfoName element to the
' EncryptedKey object.
ek.KeyInfo.AddClause(kin)
' 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)
Catch e As Exception
' re-throw the exception.
Throw
Finally
If Not (sessionKey Is Nothing) Then
sessionKey.Clear()
End If
End Try
End Sub
Public Shared 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 Class
Kompilera koden
- I ett projekt som riktar sig till .NET Framework inkluderar du en referens till
System.Security.dll. - I ett projekt som riktar sig till .NET Core eller .NET 5 installerar du NuGet-paketet System.Security.Cryptography.Xml.
- Inkludera följande namnområden: System.Xml, System.Security.Cryptographyoch System.Security.Cryptography.Xml.
.NET-säkerhet
Lagra aldrig en symmetrisk kryptografisk nyckel i klartext eller överför en symmetrisk nyckel mellan datorer i klartext. Dessutom bör du aldrig lagra eller överföra den privata nyckeln för ett asymmetriskt nyckelpar i klartext. Mer information om symmetriska och asymmetriska kryptografiska nycklar finns i Generera nycklar för kryptering och dekryptering.
Tips/Råd
För utveckling använder du Secret Manager för säker hemlig lagring. I produktion bör du överväga en produkt som Azure Key Vault.
Bädda aldrig in en nyckel direkt i källkoden. Inbäddade nycklar kan enkelt läsas från en assembly med hjälp av Ildasm.exe (IL Disassembler) eller genom att öppna assemblyn i en textredigerare, till exempel Anteckningar.
När du är klar med att använda en kryptografisk nyckel rensar du den från minnet genom att ange varje byte till noll eller genom att anropa Clear metoden för den hanterade kryptografiklassen. Kryptografiska nycklar kan ibland läsas från minnet av ett felsökningsprogram eller från en hårddisk om minnesplatsen har växlats till disk.