Como: assinar documento XML com assinaturas digitais
Você pode usar as classes no namespace System.Security.Cryptography.Xml para assinar um documento XML ou parte de um documento XML com uma assinatura digital. As XMLDSIG (assinaturas digitais XML) permitem verificar se os dados não foram alterados após a assinatura. Para obter mais informações sobre o padrão XMLDSIG, consulte a sintaxe de assinatura e o processamento XML da recomendação do World Wide Web Consortium (W3C).
Observação
O código neste artigo se aplica ao Windows.
O exemplo de código neste procedimento demonstra como assinar digitalmente um documento XML inteiro e anexar a assinatura ao documento em um elemento <Signature
>. O exemplo cria uma chave de assinatura RSA, adiciona a chave a um contêiner de chave segura e usa a chave para assinar digitalmente um documento XML. Em seguida, a chave pode ser recuperada para verificar a assinatura digital XML, ou pode ser usada para assinar outro documento XML.
Para obter informações sobre como verificar uma assinatura digital XML criada usando este procedimento, consulte Como verificar as assinaturas digitais de documentos XML.
Para assinar digitalmente um documento XML
Crie um objeto CspParameters e especifique o nome do contêiner de chaves.
CspParameters cspParams = new() { KeyContainerName = "XML_DSIG_RSA_KEY" };
Dim cspParams As New CspParameters With { .KeyContainerName = "XML_DSIG_RSA_KEY" }
Gere uma chave assimétrica usando a classe RSACryptoServiceProvider. A chave é salva automaticamente no contêiner de chaves quando você passa o objeto CspParameters para o construtor da classe RSACryptoServiceProvider. Essa chave será usada para assinar o documento XML.
RSACryptoServiceProvider rsaKey = new(cspParams);
Dim rsaKey As New RSACryptoServiceProvider(cspParams)
Crie um objeto XmlDocument carregando um arquivo XML do disco. O objeto XmlDocument contém o elemento XML a ser criptografado.
XmlDocument xmlDoc = new() { // Load an XML file into the XmlDocument object. PreserveWhitespace = true }; xmlDoc.Load("test.xml");
' Load an XML file into the XmlDocument object. Dim xmlDoc As New XmlDocument With { .PreserveWhitespace = True } xmlDoc.Load("test.xml")
Crie um objeto SignedXml e passe o objeto XmlDocument para ele.
SignedXml signedXml = new(xmlDoc) {
Dim signedXml As New SignedXml(xmlDoc)
Adicione a chave RSA de assinatura ao objeto SignedXml.
SigningKey = rsaKey };
signedXml.SigningKey = rsaKey
Crie um objeto Reference que descreve o que assinar. Para assinar o documento inteiro, defina a propriedade Uri como
""
.// Create a reference to be signed. Reference reference = new() { Uri = "" };
' Create a reference to be signed. Dim reference As New Reference() reference.Uri = ""
Adicione um objeto XmlDsigEnvelopedSignatureTransform ao objeto Reference. Uma transformação permite que o verificador represente os dados XML de maneira idêntica à que o signatário usou. Os dados XML podem ser representados de diferentes maneiras; portanto, essa etapa é vital para a verificação.
XmlDsigEnvelopedSignatureTransform env = new(); reference.AddTransform(env);
Dim env As New XmlDsigEnvelopedSignatureTransform() reference.AddTransform(env)
Adicione o objeto Reference ao objeto SignedXml.
signedXml.AddReference(reference);
signedXml.AddReference(reference)
Compute a assinatura chamando o método ComputeSignature.
signedXml.ComputeSignature();
signedXml.ComputeSignature()
Recupere a representação XML da assinatura (um elemento <
Signature
>) e salve-a em um novo objeto XmlElement.XmlElement xmlDigitalSignature = signedXml.GetXml();
Dim xmlDigitalSignature As XmlElement = signedXml.GetXml()
Acrescente o elemento ao objeto XmlDocument.
xmlDoc.DocumentElement?.AppendChild(xmlDoc.ImportNode(xmlDigitalSignature, true));
xmlDoc.DocumentElement.AppendChild(xmlDoc.ImportNode(xmlDigitalSignature, True))
Salve o documento.
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. Você pode colocar o XML a seguir em um arquivo chamado test.xml
e usá-lo com este exemplo.
<root>
<creditcard>
<number>19834209</number>
<expiry>02/02/2002</expiry>
</creditcard>
</root>
using System;
using System.Runtime.Versioning;
using System.Security.Cryptography;
using System.Security.Cryptography.Xml;
using System.Xml;
[SupportedOSPlatform("Windows")]
public class SignXML
{
public static void Main(String[] args)
{
try
{
// Create a new CspParameters object to specify
// a key container.
CspParameters cspParams = new()
{
KeyContainerName = "XML_DSIG_RSA_KEY"
};
// Create a new RSA signing key and save it in the container.
RSACryptoServiceProvider rsaKey = new(cspParams);
// Create a new XML document.
XmlDocument xmlDoc = new()
{
// Load an XML file into the XmlDocument object.
PreserveWhitespace = true
};
xmlDoc.Load("test.xml");
// Sign the XML document.
SignXml(xmlDoc, rsaKey);
Console.WriteLine("XML file signed.");
// Save the document.
xmlDoc.Save("test.xml");
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
// Sign an XML file.
// This document cannot be verified unless the verifying
// code has the key with which it was signed.
public static void SignXml(XmlDocument xmlDoc, RSA rsaKey)
{
// Check arguments.
if (xmlDoc == null)
throw new ArgumentException(null, nameof(xmlDoc));
if (rsaKey == null)
throw new ArgumentException(null, nameof(rsaKey));
// Create a SignedXml object.
SignedXml signedXml = new(xmlDoc)
{
// Add the key to the SignedXml document.
SigningKey = rsaKey
};
// Create a reference to be signed.
Reference reference = new()
{
Uri = ""
};
// Add an enveloped transformation to the reference.
XmlDsigEnvelopedSignatureTransform env = new();
reference.AddTransform(env);
// Add the reference to the SignedXml object.
signedXml.AddReference(reference);
// Compute the signature.
signedXml.ComputeSignature();
// Get the XML representation of the signature and save
// it to an XmlElement object.
XmlElement xmlDigitalSignature = signedXml.GetXml();
// Append the element to the XML document.
xmlDoc.DocumentElement?.AppendChild(xmlDoc.ImportNode(xmlDigitalSignature, true));
}
}
Imports System.Security.Cryptography
Imports System.Security.Cryptography.Xml
Imports System.Xml
Module SignXML
Sub Main(ByVal args() As String)
Try
' Create a new CspParameters object to specify
' a key container.
Dim cspParams As New CspParameters With {
.KeyContainerName = "XML_DSIG_RSA_KEY"
}
' Create a new RSA signing key and save it in the container.
Dim rsaKey As New RSACryptoServiceProvider(cspParams)
' Create a new XML document.
' Load an XML file into the XmlDocument object.
Dim xmlDoc As New XmlDocument With {
.PreserveWhitespace = True
}
xmlDoc.Load("test.xml")
' Sign the XML document.
SignXml(xmlDoc, rsaKey)
Console.WriteLine("XML file signed.")
' Save the document.
xmlDoc.Save("test.xml")
Catch e As Exception
Console.WriteLine(e.Message)
End Try
End Sub
' Sign an XML file.
' This document cannot be verified unless the verifying
' code has the key with which it was signed.
Sub SignXml(ByVal xmlDoc As XmlDocument, ByVal rsaKey As RSA)
' Check arguments.
If xmlDoc Is Nothing Then
Throw New ArgumentException(
"The XML doc cannot be nothing.", NameOf(xmlDoc))
End If
If rsaKey Is Nothing Then
Throw New ArgumentException(
"The RSA key cannot be nothing.", NameOf(rsaKey))
End If
' Create a SignedXml object.
Dim signedXml As New SignedXml(xmlDoc)
' Add the key to the SignedXml document.
signedXml.SigningKey = rsaKey
' Create a reference to be signed.
Dim reference As New Reference()
reference.Uri = ""
' Add an enveloped transformation to the reference.
Dim env As New XmlDsigEnvelopedSignatureTransform()
reference.AddTransform(env)
' Add the reference to the SignedXml object.
signedXml.AddReference(reference)
' Compute the signature.
signedXml.ComputeSignature()
' Get the XML representation of the signature and save
' it to an XmlElement object.
Dim xmlDigitalSignature As XmlElement = signedXml.GetXml()
' Append the element to the XML document.
xmlDoc.DocumentElement.AppendChild(xmlDoc.ImportNode(xmlDigitalSignature, True))
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 nem transfira a chave privada de um par de chaves assimétricas em texto sem formatação. Para mais informações sobre chaves criptográficas simétricas e assimétricas, confira Como gerar chaves para criptografia e descriptografia.
Nunca insira uma chave privada 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.