Como: descriptografar elementos XML com chaves assimétricas
Você pode usar as classes no namespace System.Security.Cryptography.Xml para criptografar e descriptografar um elemento em um documento XML. A Criptografia XML é um modo padrão de trocar ou armazenar dados XML criptografados sem se preocupar com os dados serem lidos facilmente. Para mais informações sobre o padrão de Criptografia XML, confira a Recomendação do W3C (World Wide Web Consortium) Sintaxe e processamento de assinatura XML.
Observação
O código neste artigo se aplica ao Windows.
O exemplo neste procedimento descriptografa um elemento XML que foi criptografado usando os métodos descritos em Como criptografar elementos XML com chaves assimétricas. Ele localiza um elemento <EncryptedData
>, descriptografa o elemento e substitui o elemento pelo elemento XML de texto sem formatação original.
Este exemplo descriptografa um elemento XML usando duas chaves. Ele recupera uma chave privada RSA gerada anteriormente de um contêiner de chave e usa a chave RSA para descriptografar uma chave da sessão armazenada no elemento <EncryptedKey
> do elemento <EncryptedData
>. O exemplo então usa a chave da sessão para descriptografar o elemento XML.
Esse exemplo é apropriado para situações em que vários aplicativos precisam compartilhar dados criptografados ou quando um aplicativo precisa salvar dados criptografados entre os horários em que ele é executado.
Para descriptografar um elemento XML com uma chave assimétrica
Crie um objeto CspParameters e especifique o nome do contêiner de chaves.
CspParameters cspParams = new CspParameters(); cspParams.KeyContainerName = "XML_ENC_RSA_KEY";
Dim cspParams As New CspParameters() cspParams.KeyContainerName = "XML_ENC_RSA_KEY"
Recupere uma chave assimétrica gerada anteriormente do contêiner usando o objeto RSACryptoServiceProvider. A chave é recuperada automaticamente do contêiner de chaves quando você passa o objeto CspParameters para o construtor RSACryptoServiceProvider.
RSACryptoServiceProvider rsaKey = new RSACryptoServiceProvider(cspParams);
Dim rsaKey As New RSACryptoServiceProvider(cspParams)
Crie um objeto EncryptedXml para descriptografar o documento.
// Create a new EncryptedXml object. EncryptedXml exml = new EncryptedXml(Doc);
' Create a new EncryptedXml object. Dim exml As New EncryptedXml(Doc)
Adicione um mapeamento de chave/nome para associar a chave RSA ao elemento dentro do documento que deve ser descriptografado. Você deve usar o mesmo nome para a chave usada quando criptografou o documento. Observe que esse nome é separado do nome usado para identificar a chave no contêiner de chaves especificado na etapa 1.
exml.AddKeyNameMapping(KeyName, Alg);
exml.AddKeyNameMapping(KeyName, Alg)
Chame o método DecryptDocument para descriptografar o elemento <
EncryptedData
>. Esse método usa a chave RSA para descriptografar a chave da sessão e usa automaticamente a chave da sessão para descriptografar o elemento XML. Ele também substitui automaticamente o elemento <EncryptedData
> pelo texto sem formatação original.exml.DecryptDocument();
exml.DecryptDocument()
Salve o documento XML.
xmlDoc.Save("test.xml");
xmlDoc.Save("test.xml")
Exemplo
Este exemplo pressupõe que um arquivo nomeado test.xml
exista no mesmo diretório que o programa compilado. Ele também pressupõe que test.xml
contém um elemento XML criptografado usando as técnicas descritas em Como criptografar elementos XML com chaves assimétricas.
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
Compilando o código
Em um projeto que tem como destino o .NET Framework, inclua uma referência a
System.Security.dll
.Em um projeto direcionado ao .NET Core ou ao .NET 5, instale o pacote NuGet System.Security.Cryptography.Xml.
Inclua os seguintes namespaces: System.Xml, System.Security.Cryptography e System.Security.Cryptography.Xml.
Segurança do .NET
Nunca armazene uma chave criptográfica simétrica em texto simples ou transfira uma chave simétrica entre máquinas em texto simples. Além disso, nunca armazene nem transfira a chave privada de um par de chaves assimétricas em texto não criptografado. Para obter mais informações sobre chaves criptográficas simétricas e assimétricas, confira Como gerar chaves para criptografia e descriptografia.
Nunca insira uma chave diretamente no código-fonte. As chaves inseridas podem ser facilmente lidas de um assembly usando Ildasm.exe (Desmontador IL) ou abrindo o assembly em um editor de texto, como o Bloco de Notas.
Quando você terminar de usar uma chave de criptografia, desmarque-a da memória definindo cada byte como zero ou chamando o método Clear da classe de criptografia gerenciada. Às vezes, as chaves criptográficas podem ser lidas da memória por um depurador ou lidas de um disco rígido se o local da memória for paginado em disco.