SignedXml Classe

Definição

Fornece um wrapper em um objeto de assinatura XML principal para facilitar a criação de assinaturas XML.

public ref class SignedXml
public class SignedXml
type SignedXml = class
Public Class SignedXml
Herança
SignedXml

Exemplos

O exemplo de código a seguir mostra como assinar e verificar um documento XML inteiro usando uma assinatura enveloped.

//
// This example signs an XML file using an
// envelope signature. It then verifies the 
// signed XML.
//
using System;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Security.Cryptography.Xml;
using System.Text;
using System.Xml;

public class SignVerifyEnvelope
{

    public static void Main(String[] args)
    {
        try
        {
           // Generate a signing key.
           RSA Key = RSA.Create();

           // Create an XML file to sign.
           CreateSomeXml("Example.xml");
           Console.WriteLine("New XML file created."); 

           // Sign the XML that was just created and save it in a 
           // new file.
           SignXmlFile("Example.xml", "signedExample.xml", Key);
           Console.WriteLine("XML file signed."); 

           // Verify the signature of the signed XML.
           Console.WriteLine("Verifying signature...");
           bool result = VerifyXmlFile("SignedExample.xml", Key);

           // Display the results of the signature verification to 
           // the console.
           if(result)
           {
               Console.WriteLine("The XML signature is valid.");
           }
           else
           {
            Console.WriteLine("The XML signature is not valid.");
           }
        }
        catch(CryptographicException e)
        {
            Console.WriteLine(e.Message);
        }
    }

    // Sign an XML file and save the signature in a new file. This method does not  
    // save the public key within the XML file.  This file cannot be verified unless  
    // the verifying code has the key with which it was signed.
    public static void SignXmlFile(string FileName, string SignedFileName, RSA Key)
    {
        // Create a new XML document.
        XmlDocument doc = new XmlDocument();

        // Load the passed XML file using its name.
        doc.Load(new XmlTextReader(FileName));

        // Create a SignedXml object.
        SignedXml signedXml = new SignedXml(doc);

        // Add the key to the SignedXml document. 
        signedXml.SigningKey = Key;

        // Create a reference to be signed.
        Reference reference = new Reference();
        reference.Uri = "";

        // Add an enveloped transformation to the reference.
        XmlDsigEnvelopedSignatureTransform env = 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.
        XmlElement xmlDigitalSignature = signedXml.GetXml();

        // Append the element to the XML document.
        doc.DocumentElement.AppendChild(doc.ImportNode(xmlDigitalSignature, true));
        
        if (doc.FirstChild is XmlDeclaration)  
        {
            doc.RemoveChild(doc.FirstChild);
        }

        // Save the signed XML document to a file specified
        // using the passed string.
        XmlTextWriter xmltw = new XmlTextWriter(SignedFileName, new UTF8Encoding(false));
        doc.WriteTo(xmltw);
        xmltw.Close();
    }

    // Verify the signature of an XML file against an asymmetric 
    // algorithm and return the result.
    public static Boolean VerifyXmlFile(String Name, RSA Key)
    {
        // Create a new XML document.
        XmlDocument xmlDocument = new XmlDocument();

        // Load the passed XML file into the document. 
        xmlDocument.Load(Name);

        // Create a new SignedXml object and pass it
        // the XML document class.
        SignedXml signedXml = new SignedXml(xmlDocument);

        // Find the "Signature" node and create a new
        // XmlNodeList object.
        XmlNodeList nodeList = xmlDocument.GetElementsByTagName("Signature");

        // Load the signature node.
        signedXml.LoadXml((XmlElement)nodeList[0]);

        // Check the signature and return the result.
        return signedXml.CheckSignature(Key);
    }

    // Create example data to sign.
    public static void CreateSomeXml(string FileName)
    {
        // Create a new XmlDocument object.
        XmlDocument document = new XmlDocument();

        // Create a new XmlNode object.
        XmlNode  node = document.CreateNode(XmlNodeType.Element, "", "MyElement", "samples");
        
        // Add some text to the node.
        node.InnerText = "Example text to be signed.";

        // Append the node to the document.
        document.AppendChild(node);

        // Save the XML document to the file name specified.
        XmlTextWriter xmltw = new XmlTextWriter(FileName, new UTF8Encoding(false));
        document.WriteTo(xmltw);
        xmltw.Close();
    }
}
'
' This example signs an XML file using an
' envelope signature. It then verifies the 
' signed XML.
'
Imports System.Security.Cryptography
Imports System.Security.Cryptography.X509Certificates
Imports System.Security.Cryptography.Xml
Imports System.Text
Imports System.Xml



Public Class SignVerifyEnvelope
   
   Overloads Public Shared Sub Main(args() As [String])
      Try
         ' Generate a signing key.
         Dim Key As RSA = RSA.Create()
         
         ' Create an XML file to sign.
         CreateSomeXml("Example.xml")
         Console.WriteLine("New XML file created.")
         
         ' Sign the XML that was just created and save it in a 
         ' new file.
         SignXmlFile("Example.xml", "signedExample.xml", Key)
         Console.WriteLine("XML file signed.")
         
         ' Verify the signature of the signed XML.
         Console.WriteLine("Verifying signature...")
         Dim result As Boolean = VerifyXmlFile("SignedExample.xml", Key)
         
         ' Display the results of the signature verification to 
         ' the console.
         If result Then
            Console.WriteLine("The XML signature is valid.")
         Else
            Console.WriteLine("The XML signature is not valid.")
         End If
      Catch e As CryptographicException
         Console.WriteLine(e.Message)
      End Try
   End Sub 
   
   
   
   ' Sign an XML file and save the signature in a new file. This method does not  
   ' save the public key within the XML file.  This file cannot be verified unless  
   ' the verifying code has the key with which it was signed.
   Public Shared Sub SignXmlFile(FileName As String, SignedFileName As String, Key As RSA)
      ' Create a new XML document.
      Dim doc As New XmlDocument()
      
      ' Load the passed XML file using its name.
      doc.Load(New XmlTextReader(FileName))
      
      ' Create a SignedXml object.
      Dim signedXml As New SignedXml(doc)
      
      ' Add the key to the SignedXml document. 
      signedXml.SigningKey = Key
      
      ' 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.
      doc.DocumentElement.AppendChild(doc.ImportNode(xmlDigitalSignature, True))
      
      If TypeOf doc.FirstChild Is XmlDeclaration Then
         doc.RemoveChild(doc.FirstChild)
      End If
      
      ' Save the signed XML document to a file specified
      ' using the passed string.
      Dim xmltw As New XmlTextWriter(SignedFileName, New UTF8Encoding(False))
      doc.WriteTo(xmltw)
      xmltw.Close()
   End Sub
   
   
   ' Verify the signature of an XML file against an asymmetric 
   ' algorithm and return the result.
   Public Shared Function VerifyXmlFile(Name As [String], Key As RSA) As [Boolean]
      ' Create a new XML document.
      Dim xmlDocument As New XmlDocument()
      
      ' Load the passed XML file into the document. 
      xmlDocument.Load(Name)
      
      ' Create a new SignedXml object and pass it
      ' the XML document class.
      Dim signedXml As New SignedXml(xmlDocument)
      
      ' Find the "Signature" node and create a new
      ' XmlNodeList object.
      Dim nodeList As XmlNodeList = xmlDocument.GetElementsByTagName("Signature")
      
      ' Load the signature node.
      signedXml.LoadXml(CType(nodeList(0), XmlElement))
      
      ' Check the signature and return the result.
      Return signedXml.CheckSignature(Key)
   End Function 
   
   
   
   ' Create example data to sign.
   Public Shared Sub CreateSomeXml(FileName As String)
      ' Create a new XmlDocument object.
      Dim document As New XmlDocument()
      
      ' Create a new XmlNode object.
      Dim node As XmlNode = document.CreateNode(XmlNodeType.Element, "", "MyElement", "samples")
      
      ' Add some text to the node.
      node.InnerText = "Example text to be signed."
      
      ' Append the node to the document.
      document.AppendChild(node)
      
      ' Save the XML document to the file name specified.
      Dim xmltw As New XmlTextWriter(FileName, New UTF8Encoding(False))
      document.WriteTo(xmltw)
      xmltw.Close()
   End Sub 
End Class

O exemplo de código a seguir mostra como assinar e verificar um único elemento de um documento XML usando uma assinatura de codificação.

//
// This example signs an XML file using an
// envelope signature. It then verifies the
// signed XML.
//
using System;
using System.Security.Cryptography;
using System.Security.Cryptography.Xml;
using System.Text;
using System.Xml;

public class SignVerifyEnvelope
{

    public static void Main(String[] args)
    {
        // Generate a signing key.
       RSA Key = RSA.Create();

       try
       {
           // Specify an element to sign.
           string[] elements =  { "#tag1" };

           // Sign an XML file and save the signature to a
           // new file.
           SignXmlFile("Test.xml", "SignedExample.xml", Key, elements);
           Console.WriteLine("XML file signed.");

           // Verify the signature of the signed XML.
           Console.WriteLine("Verifying signature...");

           bool result = VerifyXmlFile("SignedExample.xml");

           // Display the results of the signature verification to
           // the console.
           if (result)
           {
               Console.WriteLine("The XML signature is valid.");
           }
           else
           {
               Console.WriteLine("The XML signature is not valid.");
           }
       }
       catch (CryptographicException e)
       {
           Console.WriteLine(e.Message);
       }
       finally
       {
           // Clear resources associated with the
           // RSA instance.
           Key.Clear();
       }
   }

    // Sign an XML file and save the signature in a new file.
    public static void SignXmlFile(string FileName, string SignedFileName, RSA Key, string[] ElementsToSign)
    {
        // Check the arguments.
        if (FileName == null)
            throw new ArgumentNullException("FileName");
        if (SignedFileName == null)
            throw new ArgumentNullException("SignedFileName");
        if (Key == null)
            throw new ArgumentNullException("Key");
        if (ElementsToSign == null)
            throw new ArgumentNullException("ElementsToSign");

        // Create a new XML document.
        XmlDocument doc = new XmlDocument();

        // Format the document to ignore white spaces.
        doc.PreserveWhitespace = false;

        // Load the passed XML file using it's name.
        doc.Load(new XmlTextReader(FileName));

        // Create a SignedXml object.
        SignedXml signedXml = new SignedXml(doc);

        // Add the key to the SignedXml document.
        signedXml.SigningKey = Key;

        // Loop through each passed element to sign
        // and create a reference.
        foreach (string s in ElementsToSign)
        {
            // Create a reference to be signed.
            Reference reference = new Reference();
            reference.Uri = s;

            // Add an enveloped transformation to the reference.
            XmlDsigEnvelopedSignatureTransform env = new XmlDsigEnvelopedSignatureTransform();
            reference.AddTransform(env);

            // Add the reference to the SignedXml object.
            signedXml.AddReference(reference);
        }

        // Add an RSAKeyValue KeyInfo (optional; helps recipient find key to validate).
        KeyInfo keyInfo = new KeyInfo();
        keyInfo.AddClause(new RSAKeyValue((RSA)Key));
        signedXml.KeyInfo = keyInfo;

        // 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.
        doc.DocumentElement.AppendChild(doc.ImportNode(xmlDigitalSignature, true));

        if (doc.FirstChild is XmlDeclaration)
        {
            doc.RemoveChild(doc.FirstChild);
        }

        // Save the signed XML document to a file specified
        // using the passed string.
        XmlTextWriter xmltw = new XmlTextWriter(SignedFileName, new UTF8Encoding(false));
        doc.WriteTo(xmltw);
        xmltw.Close();
    }
    // Verify the signature of an XML file and return the result.
    public static Boolean VerifyXmlFile(String Name)
    {
        // Check the arguments.
        if (Name == null)
            throw new ArgumentNullException("Name");

        // Create a new XML document.
        XmlDocument xmlDocument = new XmlDocument();

        // Format using white spaces.
        xmlDocument.PreserveWhitespace = true;

        // Load the passed XML file into the document.
        xmlDocument.Load(Name);

        // Create a new SignedXml object and pass it
        // the XML document class.
        SignedXml signedXml = new SignedXml(xmlDocument);

        // Find the "Signature" node and create a new
        // XmlNodeList object.
        XmlNodeList nodeList = xmlDocument.GetElementsByTagName("Signature");

        // Load the signature node.
        signedXml.LoadXml((XmlElement)nodeList[0]);

        // Check the signature and return the result.
        return signedXml.CheckSignature();
    }
}
' This example signs an XML file using an
' envelope signature. It then verifies the 
' signed XML.
'
Imports System.Security.Cryptography
Imports System.Security.Cryptography.Xml
Imports System.Text
Imports System.Xml



Module SignVerifyEnvelope



    Sub Main(ByVal args() As String)
        ' Generate a signing key.
        Dim Key As RSA = RSA.Create()

        Try
            ' Specify an element to sign. 
            Dim elements As String() = New String() {"#tag1"}

            ' Sign an XML file and save the signature to a 
            ' new file.
            SignXmlFile("Test.xml", "SignedExample.xml", Key, elements)
            Console.WriteLine("XML file signed.")

            ' Verify the signature of the signed XML.
            Console.WriteLine("Verifying signature...")

            Dim result As Boolean = VerifyXmlFile("SignedExample.xml")

            ' Display the results of the signature verification to \
            ' the console.
            If result Then
                Console.WriteLine("The XML signature is valid.")
            Else
                Console.WriteLine("The XML signature is not valid.")
            End If
        Catch e As CryptographicException
            Console.WriteLine(e.Message)
        Finally
            ' Clear resources associated with the 
            ' RSA instance.
            Key.Clear()
        End Try

    End Sub


    ' Sign an XML file and save the signature in a new file.
    Sub SignXmlFile(ByVal FileName As String, ByVal SignedFileName As String, ByVal Key As RSA, ByVal ElementsToSign() As String)
        ' Check the arguments.  
        If FileName Is Nothing Then
            Throw New ArgumentNullException("FileName")
        End If
        If SignedFileName Is Nothing Then
            Throw New ArgumentNullException("SignedFileName")
        End If
        If Key Is Nothing Then
            Throw New ArgumentNullException("Key")
        End If
        If ElementsToSign Is Nothing Then
            Throw New ArgumentNullException("ElementsToSign")
        End If
        ' Create a new XML document.
        Dim doc As New XmlDocument()

        ' Format the document to ignore white spaces.
        doc.PreserveWhitespace = False

        ' Load the passed XML file using it's name.
        doc.Load(New XmlTextReader(FileName))

        ' Create a SignedXml object.
        Dim signedXml As New SignedXml(doc)

        ' Add the key to the SignedXml document. 
        signedXml.SigningKey = Key

        ' Loop through each passed element to sign 
        ' and create a reference.
        Dim s As String
        For Each s In ElementsToSign
            ' Create a reference to be signed.
            Dim reference As New Reference()
            reference.Uri = s

            ' 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)
        Next s

        ' Add an RSAKeyValue KeyInfo (optional; helps recipient find key to validate).
        Dim keyInfo As New KeyInfo()
        keyInfo.AddClause(New RSAKeyValue(CType(Key, RSA)))
        signedXml.KeyInfo = keyInfo

        ' 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.
        doc.DocumentElement.AppendChild(doc.ImportNode(xmlDigitalSignature, True))


        If TypeOf doc.FirstChild Is XmlDeclaration Then
            doc.RemoveChild(doc.FirstChild)
        End If

        ' Save the signed XML document to a file specified
        ' using the passed string.
        Dim xmltw As New XmlTextWriter(SignedFileName, New UTF8Encoding(False))
        doc.WriteTo(xmltw)
        xmltw.Close()

    End Sub

    ' Verify the signature of an XML file and return the result.
    Function VerifyXmlFile(ByVal Name As String) As [Boolean]
        ' Check the arguments.  
        If Name Is Nothing Then
            Throw New ArgumentNullException("Name")
        End If
        ' Create a new XML document.
        Dim xmlDocument As New XmlDocument()

        ' Format using white spaces.
        xmlDocument.PreserveWhitespace = True

        ' Load the passed XML file into the document. 
        xmlDocument.Load(Name)

        ' Create a new SignedXml object and pass it
        ' the XML document class.
        Dim signedXml As New SignedXml(xmlDocument)

        ' Find the "Signature" node and create a new
        ' XmlNodeList object.
        Dim nodeList As XmlNodeList = xmlDocument.GetElementsByTagName("Signature")

        ' Load the signature node.
        signedXml.LoadXml(CType(nodeList(0), XmlElement))

        ' Check the signature and return the result.
        Return signedXml.CheckSignature()

    End Function
End Module

Comentários

A SignedXml classe é a implementação do .NET da Sintaxe de Assinatura XML do W3C (World Wide Web Consortium), também conhecida como XMLDSIG (Assinatura Digital XML). O XMLDSIG é uma maneira interoperável baseada em padrões de assinar e verificar tudo ou parte de um documento XML ou outros dados que podem ser endereçáveis de um URI (Uniform Resource Identifier).

Use a SignedXml classe sempre que precisar compartilhar dados XML assinados entre aplicativos ou organizações de maneira padrão. Todos os dados assinados usando essa classe podem ser verificados por qualquer implementação em conformidade da especificação W3C para XMLDSIG.

A SignedXml classe permite que você crie os três tipos de assinaturas digitais XML a seguir:

Tipo de assinatura Description
Assinatura envelopada A assinatura está contida no elemento XML que está sendo assinado.
Envolvendo a assinatura O XML assinado está contido no <Signature> elemento.
Assinatura desanexada interna A assinatura e o XML assinado estão no mesmo documento, mas nenhum dos elementos contém o outro.

Há também um quarto tipo de assinatura chamado uma assinatura desanexada externa, que é quando os dados e a assinatura estão em documentos XML separados. Não há suporte para assinaturas externas desanexadas pela classe SignedXml.

Estrutura de uma assinatura XML

XMLDSIG cria um <Signature> elemento, que contém uma assinatura digital de um documento XML ou outros dados que podem ser endereçáveis de um URI. Opcionalmente <Signature> , o elemento pode conter informações sobre onde encontrar uma chave que verificará a assinatura e qual algoritmo criptográfico foi usado para assinatura. A estrutura básica é a seguinte:

<Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
    <SignedInfo>
      <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
      <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
      <Reference URI="">
        <Transforms>
          <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
        </Transforms>
        <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
        <DigestValue>Base64EncodedValue==</DigestValue>
      </Reference>
    </SignedInfo>
    <SignatureValue>AnotherBase64EncodedValue===</SignatureValue>
</Signature>

As principais partes dessa estrutura são:

  • O elemento <CanonicalizationMethod>

    Especifica as regras para reescrever o Signature elemento de XML/texto em bytes para validação de assinatura. O valor padrão no .NET é http://www.w3.org/TR/2001/REC-xml-c14n-20010315, que identifica um algoritmo confiável. Esse elemento é representado pela SignedInfo.CanonicalizationMethod propriedade.

  • O elemento <SignatureMethod>

    Especifica o algoritmo usado para geração e validação de assinatura, que foi aplicado ao <Signature> elemento para produzir o valor em <SignatureValue>. No exemplo anterior, o valor http://www.w3.org/2000/09/xmldsig#rsa-sha1 identifica uma assinatura RSA PKCS1 SHA-1. Devido a problemas de colisão com SHA-1, a Microsoft recomenda um modelo de segurança baseado no SHA-256 ou superior. Esse elemento é representado pela SignatureMethod propriedade.

  • O elemento <SignatureValue>

    Especifica a assinatura criptográfica para o <Signature> elemento. Se essa assinatura não for verificada, parte do <Signature> bloco foi adulterada e o documento será considerado inválido. Desde que o <CanonicalizationMethod> valor seja confiável, esse valor é altamente resistente à adulteração. Esse elemento é representado pela SignatureValue propriedade.

  • O URI atributo do <Reference> elemento

    Especifica um objeto de dados usando uma referência de URI. Esse atributo é representado pela Reference.Uri propriedade.

    • Não especificar o URI atributo, ou seja, definir a Reference.Uri propriedade como null, significa que o aplicativo receptor deve saber a identidade do objeto. Na maioria dos casos, um null URI resultará na geração de uma exceção. Não use um null URI, a menos que seu aplicativo esteja interoperando com um protocolo que o exija.

    • Definir o URI atributo como uma string vazia indica que o elemento raiz do documento está sendo assinado, uma forma de assinatura envelopada.

    • Se o valor do URI atributo começar com #, o valor deverá ser resolvido para um elemento no documento atual. Esse formulário pode ser usado com qualquer um dos tipos de assinatura com suporte (assinatura envelopada, assinatura envelopante ou assinatura desanexada interna).

    • Qualquer outra coisa é considerada uma assinatura desvinculada de recursos externos e não tem suporte pela classe SignedXml.

  • O elemento <Transforms>

    Contém uma lista ordenada de <Transform> elementos que descrevem como o signatário obteve o objeto de dados que foi digerido. Um algoritmo de transformação é semelhante ao método de canonicalização, mas em vez de reescrever o <Signature> elemento, ele reescreve o conteúdo identificado pelo URI atributo do <Reference> elemento. O <Transforms> elemento é representado pela TransformChain classe.

    • Cada algoritmo de transformação é definido como usar XML (um conjunto de nós XPath) ou bytes como entrada. Se o formato dos dados atuais for diferente dos requisitos de entrada de transformação, as regras de conversão serão aplicadas.

    • Cada algoritmo de transformação é definido como produzindo XML ou bytes como saída.

    • Se a saída do algoritmo de última transformação não for definida em bytes (ou nenhuma transformação foi especificada), o método de canonicalização será usado como uma transformação implícita (mesmo que um algoritmo diferente tenha sido especificado no <CanonicalizationMethod> elemento).

    • Um valor de http://www.w3.org/2000/09/xmldsig#enveloped-signature do algoritmo de transformação codifica uma regra que é interpretada como remover o elemento <Signature> do documento. Caso contrário, um verificador de uma assinatura envelopada digerirá o documento, incluindo a assinatura; no entanto, o signatário já teria digerido o documento antes de a assinatura ser aplicada, resultando em respostas diferentes.

  • O elemento <DigestMethod>

    Identifica o método digest (hash criptográfico) a ser aplicado ao conteúdo transformado identificado pelo atributo URI do elemento <Reference>. Isso é representado pela propriedade Reference.DigestMethod.

Escolhendo um método de canonicalização

A menos que interopere com uma especificação que exija o uso de um valor diferente, recomendamos que você use o método de canonicalização padrão do .NET, que é o algoritmo XML-C14N 1.0, cujo valor é http://www.w3.org/TR/2001/REC-xml-c14n-20010315. O algoritmo XML-C14N 1.0 é necessário para ser suportado por todas as implementações de XMLDSIG, especialmente porque é uma transformação final implícita a ser aplicada.

Há versões de algoritmos de canonicalização que dão suporte à preservação de comentários. Métodos de canonicalização que preservam comentários não são recomendados porque violam o princípio "assinar o que é visto". Ou seja, os comentários em um <Signature> elemento não alterarão a lógica de processamento de como a assinatura é executada, apenas qual é o valor da assinatura. Quando combinado com um algoritmo de assinatura fraco, permitir que os comentários sejam incluídos dá a um invasor liberdade desnecessária para forçar uma colisão de hash, fazendo com que um documento adulterado pareça legítimo. No .NET Framework, há suporte apenas para canonizadores internos por padrão. Para dar suporte a canonizadores adicionais ou personalizados, consulte a SafeCanonicalizationMethods propriedade. Se o documento usar um método de canonicalização que não está na coleção representada pela SafeCanonicalizationMethods propriedade, o CheckSignature método retornará false.

Note

Um aplicativo extremamente defensivo pode remover todos os valores que não espera que os signatários usem da SafeCanonicalizationMethods coleção.

Os valores de referência estão a salvo de adulteração?

Sim, os <Reference> valores estão a salvo de adulteração. O .NET verifica a <SignatureValue> computação antes de processar os <Reference> valores e suas transformações associadas, e interromperá antecipadamente para evitar instruções de processamento potencialmente mal-intencionadas.

Escolha os elementos a serem assinados

Recomendamos que você use o valor de "" para o URI atributo (ou defina a Uri propriedade como uma cadeia de caracteres vazia), se possível. Isso significa que todo o documento é considerado para a computação de resumo, o que significa que todo o documento está protegido contra adulteração.

É muito comum ver URI valores na forma de âncoras como #foo, referindo-se a um elemento cujo atributo de ID é "foo". Infelizmente, é fácil que isso seja adulterado porque isso inclui apenas o conteúdo do elemento de destino, não o contexto. Abusar dessa distinção é conhecido como XSW (Encapsulamento de Assinatura XML).

Se seu aplicativo considerar os comentários semânticos (o que não é comum ao lidar com XML), você deverá usar "#xpointer(/)" em vez de "" e "#xpointer(id('foo'))" em vez de "#foo". As versões #xpointer são interpretadas como incluindo comentários, enquanto as formas de nome abreviado excluem comentários.

Se você precisar aceitar documentos que estão apenas parcialmente protegidos e quiser garantir que você esteja lendo o mesmo conteúdo protegido pela assinatura, use o GetIdElement método.

Considerações de segurança sobre o elemento KeyInfo

Os dados no elemento opcional <KeyInfo> (ou seja, a KeyInfo propriedade), que contém uma chave para validar a assinatura, não devem ser confiáveis.

Em particular, quando o KeyInfo valor representa uma chave pública RSA, DSA ou ECDSA nua, o documento pode ter sido adulterado, apesar do CheckSignature método relatar que a assinatura é válida. Isso pode acontecer porque a entidade que está fazendo a adulteração só precisa gerar uma nova chave e assinar novamente o documento adulterado com essa nova chave. Portanto, a menos que seu aplicativo verifique se a chave pública é um valor esperado, o documento deve ser tratado como se tivesse sido adulterado. Isso requer que seu aplicativo examine a chave pública inserida no documento e verifique-a em uma lista de valores conhecidos para o contexto do documento. Por exemplo, se o documento pudesse ser entendido como emitido por um usuário conhecido, você verificaria a chave em uma lista de chaves conhecidas usadas por esse usuário.

Você também pode verificar a chave depois de processar o documento usando o CheckSignatureReturningKey método, em vez de usar o CheckSignature método. Mas, para a segurança ideal, você deve verificar a chave com antecedência.

Como alternativa, considere tentar as chaves públicas registradas do usuário, em vez de ler o que está no <KeyInfo> elemento.

Considerações de segurança sobre o elemento X509Data

O elemento opcional <X509Data> é um filho do <KeyInfo> elemento e contém um ou mais certificados X509 ou identificadores para certificados X509. Os dados no <X509Data> elemento também não devem ser inerentemente confiáveis.

Ao verificar um documento com o elemento inserido <X509Data> , o .NET verifica apenas se os dados são resolvidos para um certificado X509 cuja chave pública pode ser usada com êxito para validar a assinatura do documento. Ao contrário de chamar o método CheckSignature com o parâmetro verifySignatureOnly definido como false, nenhuma verificação de revogação é executada, nenhuma relação de confiança de cadeia é verificada e nenhuma verificação de expiração é realizada. Mesmo que seu aplicativo extraia o certificado em si e o transmita para o método CheckSignature com o parâmetro verifySignatureOnly definido como false, isso ainda não é validação suficiente para evitar a adulteração de documentos. O certificado ainda precisa ser verificado como sendo apropriado para o documento que está sendo assinado.

O uso de um certificado de assinatura inserido pode fornecer estratégias úteis de rotação de chaves, seja na <X509Data> seção ou no conteúdo do documento. Ao usar essa abordagem, um aplicativo deve extrair o certificado manualmente e executar uma validação semelhante a:

  • O certificado foi emitido diretamente ou por meio de uma cadeia por uma AC (Autoridade de Certificação) cujo certificado público está inserido no aplicativo.

    Usar a lista de confiança fornecida pelo sistema operacional sem verificações adicionais, como um nome de assunto conhecido, não é suficiente para evitar a adulteração em SignedXml.

  • Verifica-se que o certificado não expirou no momento da assinatura do documento (ou "agora" para processamento quase em tempo real de documentos).

  • Para certificados de longa duração emitidos por uma CA que suporta revogação, verifique se o certificado não foi revogado.

  • O titular do certificado é verificado como sendo apropriado para o documento atual.

Escolhendo o algoritmo de transformação

Se você estiver interoperando com uma especificação que tenha determinado valores específicos (como XrML), será necessário seguir a especificação. Se você tiver uma assinatura envelopeada (como ao assinar o documento inteiro), precisará usar http://www.w3.org/2000/09/xmldsig#enveloped-signature (representado pela XmlDsigEnvelopedSignatureTransform classe). Você também pode especificar a transformação de XML-C14N implícita, mas não é necessário. Para uma assinatura envolvente ou desanexada, nenhuma transformação é necessária. A transformação XML-C14N implícita cuida de tudo.

Com a atualização de segurança introduzida pelo boletim Segurança da Microsoft MS16-035, .NET restringiu quais transformações podem ser usadas na verificação de documentos por padrão. Transformações não confiáveis fazem CheckSignature com que sempre retornem false. Em particular, transformações que exigem entrada adicional (especificadas como elementos filho no XML) não são permitidas devido à suscetibilidade de abuso por usuários mal-intencionados. O W3C aconselha evitar as transformações XPath e XSLT, que são as duas principais transformações afetadas por essas restrições.

O problema com referências externas

Se um aplicativo não verificar se as referências externas parecem apropriadas para o contexto atual, elas poderão ser abusadas de maneiras que resultam em muitas vulnerabilidades de segurança (incluindo negação de serviço, negação de serviço de reflexão distribuída, divulgação de informações, bypass de verificação de assinatura e execução remota de código). Mesmo se um aplicativo validasse o URI de referência externa, ainda haveria um problema de o recurso ser carregado duas vezes: uma vez quando seu aplicativo o lê e uma vez quando SignedXml o lê. Como não há garantia de que as etapas de verificação de documentos e leitura do aplicativo tenham o mesmo conteúdo, a assinatura não fornece confiabilidade.

Considerando os riscos de referências externas, SignedXml gera uma exceção quando uma referência externa é encontrada. Para obter mais informações sobre esse problema, consulte .NET aplicativos encontrarem erros de exceção.

Construtores

Nome Description
SignedXml()

Inicializa uma nova instância da classe SignedXml.

SignedXml(XmlDocument)

Inicializa uma nova instância da classe do SignedXml documento XML especificado.

SignedXml(XmlElement)

Inicializa uma nova instância da classe do SignedXml objeto especificado XmlElement .

Campos

Nome Description
m_signature

Representa o Signature objeto do objeto atual SignedXml .

m_strSigningKeyName

Representa o nome da chave instalada a ser usada para assinar o SignedXml objeto.

XmlDecryptionTransformUrl

Representa o URI (Uniform Resource Identifier) para a transformação de descriptografia do modo XML. Esse campo é constante.

XmlDsigBase64TransformUrl

Representa o URI (Uniform Resource Identifier) para a transformação base 64. Esse campo é constante.

XmlDsigC14NTransformUrl

Representa o URI (Uniform Resource Identifier) para a transformação XML canônica. Esse campo é constante.

XmlDsigC14NWithCommentsTransformUrl

Representa o URI (Uniform Resource Identifier) para a transformação XML canônica, com comentários. Esse campo é constante.

XmlDsigCanonicalizationUrl

Representa o URI (Uniform Resource Identifier) para o algoritmo de canonicalização padrão para assinaturas digitais XML. Esse campo é constante.

XmlDsigCanonicalizationWithCommentsUrl

Representa o URI (Uniform Resource Identifier) para o algoritmo de canonicalização padrão para assinaturas digitais XML e inclui comentários. Esse campo é constante.

XmlDsigDSAUrl

Representa o URI (Uniform Resource Identifier) para o algoritmo padrão DSA para assinaturas digitais XML. Esse campo é constante.

XmlDsigEnvelopedSignatureTransformUrl

Representa o URI (Uniform Resource Identifier) para a transformação de assinatura enveloped. Esse campo é constante.

XmlDsigExcC14NTransformUrl

Representa o URI (Uniform Resource Identifier) para canonização exclusiva de XML. Esse campo é constante.

XmlDsigExcC14NWithCommentsTransformUrl

Representa o URI (Uniform Resource Identifier) para canonização exclusiva de XML, com comentários. Esse campo é constante.

XmlDsigHMACSHA1Url

Representa o URI (Uniform Resource Identifier) para o algoritmo padrão HMACSHA1 para assinaturas digitais XML. Esse campo é constante.

XmlDsigMinimalCanonicalizationUrl

Representa o URI (Uniform Resource Identifier) para o algoritmo de canonicalização mínimo padrão para assinaturas digitais XML. Esse campo é constante.

XmlDsigNamespaceUrl

Representa o URI (Uniform Resource Identifier) para o namespace padrão para assinaturas digitais XML. Esse campo é constante.

XmlDsigRSASHA1Url

Representa o URI (Uniform Resource Identifier) para o método de assinatura padrão RSA para assinaturas digitais XML. Esse campo é constante.

XmlDsigRSASHA256Url

Representa o URI (Uniform Resource Identifier) para a variação do RSA método de assinatura SHA-256 para assinaturas digitais XML. Esse campo é constante.

XmlDsigRSASHA384Url

Representa o URI (Uniform Resource Identifier) para a variação do RSA método de assinatura SHA-384 para assinaturas digitais XML. Esse campo é constante.

XmlDsigRSASHA512Url

Representa o URI (Uniform Resource Identifier) para a variação do RSA método de assinatura SHA-512 para assinaturas digitais XML. Esse campo é constante.

XmlDsigSHA1Url

Representa o URI (Uniform Resource Identifier) para o método de resumo padrão SHA1 para assinaturas digitais XML. Esse campo é constante.

XmlDsigSHA256Url

Representa o URI (Uniform Resource Identifier) para o método de resumo padrão SHA256 para assinaturas digitais XML. Esse campo é constante.

XmlDsigSHA384Url

Representa o URI (Uniform Resource Identifier) para o método de resumo padrão SHA384 para assinaturas digitais XML. Esse campo é constante.

XmlDsigSHA512Url

Representa o URI (Uniform Resource Identifier) para o método de resumo padrão SHA512 para assinaturas digitais XML. Esse campo é constante.

XmlDsigXPathTransformUrl

Representa o URI (Uniform Resource Identifier) para a XPath (Linguagem de Caminho XML). Esse campo é constante.

XmlDsigXsltTransformUrl

Representa o URI (Uniform Resource Identifier) para transformações XSLT. Esse campo é constante.

XmlLicenseTransformUrl

Representa o URI (Uniform Resource Identifier) para o algoritmo de transformação de licença usado para normalizar licenças XrML para assinaturas.

Propriedades

Nome Description
EncryptedXml

Obtém ou define um EncryptedXml objeto que define as regras de processamento de criptografia XML.

KeyInfo

Obtém ou define o KeyInfo objeto do objeto atual SignedXml .

Resolver

Define o objeto atual XmlResolver .

SafeCanonicalizationMethods

Obtém os nomes dos métodos cujos algoritmos de canonicalização são explicitamente permitidos.

Signature

Obtém o Signature objeto do objeto atual SignedXml .

SignatureFormatValidator

Obtém um delegado que será chamado para validar o formato (não a segurança criptográfica) de uma assinatura XML.

SignatureLength

Obtém o comprimento da assinatura do objeto atual SignedXml .

SignatureMethod

Obtém o método de assinatura do objeto atual SignedXml .

SignatureValue

Obtém o valor de assinatura do objeto atual SignedXml .

SignedInfo

Obtém o SignedInfo objeto do objeto atual SignedXml .

SigningKey

Obtém ou define a chave de algoritmo assimétrica usada para assinar um SignedXml objeto.

SigningKeyName

Obtém ou define o nome da chave instalada a ser usada para assinar o SignedXml objeto.

Métodos

Nome Description
AddObject(DataObject)

Adiciona um DataObject objeto à lista de objetos a serem assinados.

AddReference(Reference)

Adiciona um Reference objeto ao SignedXml objeto que descreve um método digest, valor digest e transformação a ser usado para criar uma assinatura digital XML.

CheckSignature()

Determina se a Signature propriedade verifica o uso da chave pública na assinatura.

CheckSignature(AsymmetricAlgorithm)

Determina se a Signature propriedade verifica a chave especificada.

CheckSignature(KeyedHashAlgorithm)

Determina se a Signature propriedade verifica o algoritmo mac (código de autenticação de mensagem) especificado.

CheckSignature(X509Certificate2, Boolean)

Determina se a Signature propriedade verifica se o objeto especificado X509Certificate2 e, opcionalmente, se o certificado é válido.

CheckSignatureReturningKey(AsymmetricAlgorithm)

Determina se a Signature propriedade verifica o uso da chave pública na assinatura.

ComputeSignature()

Calcula uma assinatura digital XML.

ComputeSignature(KeyedHashAlgorithm)

Calcula uma assinatura digital XML usando o algoritmo mac (código de autenticação de mensagem) especificado.

Equals(Object)

Determina se o objeto especificado é igual ao objeto atual.

(Herdado de Object)
GetHashCode()

Serve como a função de hash padrão.

(Herdado de Object)
GetIdElement(XmlDocument, String)

Retorna o XmlElement objeto com a ID especificada do objeto especificado XmlDocument .

GetPublicKey()

Retorna a chave pública de uma assinatura.

GetType()

Obtém o Type da instância atual.

(Herdado de Object)
GetXml()

Retorna a representação XML de um SignedXml objeto.

LoadXml(XmlElement)

Carrega um SignedXml estado de um elemento XML.

MemberwiseClone()

Cria uma cópia superficial do Objectatual.

(Herdado de Object)
ToString()

Retorna uma cadeia de caracteres que representa o objeto atual.

(Herdado de Object)

Aplica-se a

Confira também