SignedXml Clase
Definición
Importante
Parte de la información hace referencia a la versión preliminar del producto, que puede haberse modificado sustancialmente antes de lanzar la versión definitiva. Microsoft no otorga ninguna garantía, explícita o implícita, con respecto a la información proporcionada aquí.
Proporciona un contenedor en un objeto de firma XML principal para facilitar la creación de firmas XML.
public ref class SignedXml
public class SignedXml
type SignedXml = class
Public Class SignedXml
- Herencia
-
SignedXml
Ejemplos
En el ejemplo de código siguiente se muestra cómo firmar y comprobar un documento XML completo mediante una firma sobre.
//
// 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
En el ejemplo de código siguiente se muestra cómo firmar y comprobar un único elemento de un documento XML mediante una firma envolvente.
//
// 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
Comentarios
La SignedXml clase es la implementación de .NET de la sintaxis y la especificación de procesamiento de firmas XML de World Wide Web Consortium (W3C), también conocida como XMLDSIG (firma digital XML). XMLDSIG es una manera interoperable y basada en estándares para firmar y comprobar todo o parte de un documento XML u otros datos direccionables desde un identificador uniforme de recursos (URI).
Use la SignedXml clase siempre que necesite compartir datos XML firmados entre aplicaciones u organizaciones de forma estándar. Cualquier dato firmado con esta clase se puede comprobar mediante cualquier implementación conforme de la especificación W3C para XMLDSIG.
La SignedXml clase permite crear los tres tipos siguientes de firmas digitales XML:
| Tipo de firma | Description |
|---|---|
| Firma encapsulada | La firma está contenida en el elemento XML que se está firmando. |
| Firma envolvente | El XML firmado está incluido en el <Signature> elemento . |
| Firma separada interna | La firma y el XML firmado están en el mismo documento, pero ninguno de los elementos contiene el otro. |
También hay un cuarto tipo de firma denominada firma desasociada externa que es cuando los datos y la firma están en documentos XML independientes. La SignedXml clase no admite firmas desasociadas externas.
Estructura de una firma XML
XMLDSIG crea un <Signature> elemento, que contiene una firma digital de un documento XML u otros datos direccionables desde un URI. Opcionalmente, el <Signature> elemento puede contener información sobre dónde encontrar una clave que comprobará la firma y qué algoritmo criptográfico se usó para firmar. La estructura básica es la siguiente:
<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>
Las partes principales de esta estructura son:
El elemento
<CanonicalizationMethod>Especifica las reglas para volver a escribir el
Signatureelemento de XML/text en bytes para la validación de firmas. El valor predeterminado de .NET es http://www.w3.org/TR/2001/REC-xml-c14n-20010315, que identifica un algoritmo de confianza. Este elemento se representa mediante la SignedInfo.CanonicalizationMethod propiedad .El elemento
<SignatureMethod>Especifica el algoritmo usado para la generación y validación de firmas, que se aplicó al
<Signature>elemento para generar el valor en<SignatureValue>. En el ejemplo anterior, el valor http://www.w3.org/2000/09/xmldsig#rsa-sha1 identifica una firma RSA PKCS1 SHA-1. Debido a problemas de colisión con SHA-1, Microsoft recomienda un modelo de seguridad basado en SHA-256 o superior. Este elemento se representa mediante la SignatureMethod propiedad .El elemento
<SignatureValue>Especifica la firma criptográfica para el
<Signature>elemento . Si esta firma no comprueba, se ha alterado alguna parte del<Signature>bloque y el documento se considera no válido. Siempre que el<CanonicalizationMethod>valor sea de confianza, este valor es altamente resistente a la manipulación. Este elemento se representa mediante la SignatureValue propiedad .Atributo
URIdel<Reference>elementoEspecifica un objeto de datos mediante una referencia de URI. Este atributo se representa mediante la Reference.Uri propiedad .
No especificar el atributo
URI, es decir, establecer la propiedad Reference.Uri al valornull, significa que se espera que la aplicación receptora conozca la identidad del objeto. En la mayoría de los casos, unnullURI producirá una excepción. No use unnullURI, a menos que la aplicación interopera con un protocolo que lo requiera.Si se establece el atributo
URIen una cadena vacía, esto indica que se está firmando el elemento raíz del documento, una forma de firma envolvente.Si el valor del
URIatributo comienza con #, el valor debe resolverse en un elemento del documento actual. Este formulario se puede usar con cualquiera de los tipos de firma admitidos (firma envuelta, firma envolvente o firma desasociada interna).Cualquier otra cosa se considera una firma desasociada de recursos externos y no es compatible con la SignedXml clase .
El elemento
<Transforms>Contiene una lista ordenada de
<Transform>elementos que describen cómo el firmante obtuvo el objeto de datos que fue procesado. Un algoritmo de transformación es similar al método de canonización, pero en lugar de reescribir el elemento<Signature>, reescribe el contenido identificado por el atributoURIdel elemento<Reference>. El<Transforms>elemento se representa mediante la TransformChain clase .Cada algoritmo de transformación se define por aceptar como entrada XML (un conjunto de nodos XPath) o bytes. Si el formato de los datos actuales difiere de los requisitos de entrada de transformación, se aplican reglas de conversión.
Cada algoritmo de transformación se define como producir XML o bytes como salida.
Si la salida del último algoritmo de transformación no está definida en bytes (o no se especificaron transformaciones), el método de canónica se usa como una transformación implícita (incluso si se especificó un algoritmo diferente en el
<CanonicalizationMethod>elemento).Un valor de http://www.w3.org/2000/09/xmldsig#enveloped-signature para el algoritmo de transformación codifica una regla que se interpreta como quitar el
<Signature>elemento del documento. De lo contrario, un verificador de una firma envuelta procesará el documento, incluida la firma, pero el firmante habrá procesado el documento antes de aplicar la firma, lo que conduce a respuestas diferentes.
El elemento
<DigestMethod>Identifica el método digest (hash criptográfico) que se va a aplicar al contenido transformado identificado por el atributo
URIdel elemento<Reference>. Esto se representa mediante la Reference.DigestMethod propiedad .
Elección de un método de canonicación
A menos que esté interoperando con una especificación que requiera el uso de un valor diferente, le recomendamos que use el método de canonización predeterminado de .NET, que es el algoritmo XML-C14N de la versión 1.0, cuyo valor es http://www.w3.org/TR/2001/REC-xml-c14n-20010315. El algoritmo XML-C14N 1.0 debe ser compatible con todas las implementaciones de XMLDSIG, especialmente cuando se trata de una transformación final implícita que se va a aplicar.
Hay versiones de algoritmos de canónica que admiten la conservación de comentarios. No se recomienda el uso de métodos de canonización que conserven comentarios porque violan el principio de "firmar lo que se ve". Es decir, los comentarios de un <Signature> elemento no modificarán la lógica de procesamiento de cómo se realiza la firma, simplemente lo que es el valor de la firma. Cuando se combina con un algoritmo de firma débil, lo que permite que los comentarios se incluyan proporcionan a un atacante libertad innecesaria para forzar una colisión de hash, lo que hace que un documento manipulado parezca legítimo. En .NET Framework, solo se admiten los canonalizadores integrados por defecto. Para admitir canonicalizadores adicionales o personalizados, consulte la propiedad SafeCanonicalizationMethods. Si el documento utiliza un método de canonización que no está en la colección representada por la SafeCanonicalizationMethods propiedad, CheckSignature devolverá false.
Note
Una aplicación extremadamente defensiva puede quitar los valores que no espera que los firmantes usen de la SafeCanonicalizationMethods colección.
¿Los valores de referencia están a salvo de la manipulación?
Sí, los valores <Reference> están protegidos contra la alteración. .NET comprueba el proceso <SignatureValue> antes de procesar cualquiera de los valores <Reference> y sus transformaciones asociadas, y anulará pronto para evitar instrucciones de procesamiento potencialmente malintencionadas.
Elegir los elementos que se van a firmar
Se recomienda usar el valor de "" para el URI atributo (o establecer la Uri propiedad en una cadena vacía), si es posible. Esto significa que todo el documento se considera para el cálculo de resumen, lo que significa que todo el documento está protegido contra alteraciones.
Es muy común ver URI valores en forma de anclajes como #foo, haciendo referencia a un elemento cuyo atributo id. es "foo". Desafortunadamente, es fácil que esto se manipule porque esto incluye solo el contenido del elemento de destino, no el contexto. El abuso de esta distinción se conoce como envoltura de firma XML (XSW).
Si la aplicación considera que los comentarios son semánticos (que no son comunes al tratar con XML), debe usar "#xpointer(/)" en lugar de "" y "#xpointer(id('foo'))" en lugar de "#foo". Las versiones de #xpointer se interpretan como que incluyen comentarios, mientras que las formas abreviadas excluyen los comentarios.
Si necesita aceptar documentos que solo están parcialmente protegidos y desea asegurarse de que está leyendo el mismo contenido protegido por la firma, use el GetIdElement método .
Consideraciones de seguridad sobre el elemento KeyInfo
Los datos del elemento opcional <KeyInfo> (es decir, la KeyInfo propiedad ), que contiene una clave para validar la firma, no deben ser de confianza.
En concreto, cuando el valor KeyInfo representa una clave pública RSA, DSA o ECDSA en bruto, el documento podría haber sido manipulado, a pesar de que el método CheckSignature informa que la firma es válida. Esto puede ocurrir porque la entidad que realiza la manipulación solo tiene que generar una nueva clave y volver a firmar el documento alterado con esa nueva clave. Por lo tanto, a menos que la aplicación compruebe que la clave pública es un valor esperado, el documento debe tratarse como si se alterara. Esto requiere que la aplicación examine la clave pública insertada en el documento y compruébala en una lista de valores conocidos para el contexto del documento. Por ejemplo, si se pudiera interpretar que el documento fue emitido por un usuario conocido, comprobarías la clave en una lista de claves conocidas utilizadas por ese usuario.
También puede comprobar la clave después de procesar el documento mediante el CheckSignatureReturningKey método , en lugar de usar el CheckSignature método . Sin embargo, para obtener la seguridad óptima, debe comprobar la clave de antemano.
Como alternativa, considere la posibilidad de probar las claves públicas registradas del usuario, en lugar de leer lo que hay en el <KeyInfo> elemento .
Consideraciones de seguridad sobre el elemento X509Data
El elemento opcional es un elemento secundario <X509Data> del <KeyInfo> elemento y contiene uno o varios certificados o identificadores X509 para los certificados X509. Los datos del <X509Data> elemento tampoco deben ser de confianza inherente.
Al comprobar un documento con el elemento incrustado <X509Data> , .NET comprueba solo que los datos se resuelven en un certificado X509 cuya clave pública se puede usar correctamente para validar la firma del documento. A diferencia de llamar al método CheckSignature con el parámetro verifySignatureOnly establecido en false, no se realiza ninguna verificación de revocación, no se comprueba la confianza en la cadena y no se verifica la expiración. Incluso si la aplicación extrae el propio certificado y lo pasa al método CheckSignature con el parámetro verifySignatureOnly establecido en false, eso aún no es una validación suficiente para evitar la manipulación de documentos. El certificado todavía debe comprobarse según sea adecuado para el documento que se está firmando.
El uso de un certificado de firma incrustado puede proporcionar estrategias de rotación de claves útiles, ya sea en la <X509Data> sección o en el contenido del documento. Al usar este enfoque, una aplicación debe extraer el certificado manualmente y realizar la validación similar a:
El certificado se emitió directamente o a través de una cadena por una entidad de certificación (CA) cuyo certificado público está incrustado en la aplicación.
El uso de la lista de confianza proporcionada por el sistema operativo sin comprobaciones adicionales, como un nombre de sujeto conocido, no es suficiente para evitar alteraciones en SignedXml.
Se comprueba que el certificado no ha expirado en el momento de la firma de documentos (o "ahora" para el procesamiento de documentos casi en tiempo real).
Para los certificados de larga duración emitidos por una ENTIDAD de certificación que admite la revocación, compruebe que el certificado no se revoca.
El sujeto del certificado se verifica que sea apropiado para el documento actual.
Elección del algoritmo de transformación
Si interopera con una especificación que ha dictado valores específicos (como XrML), debe seguir la especificación. Si tiene una firma envuelta (como cuando firma todo el documento), debe usar http://www.w3.org/2000/09/xmldsig#enveloped-signature (representada por la clase XmlDsigEnvelopedSignatureTransform). También puede especificar la transformación implícita de XML-C14N, pero no es necesario hacerlo. Para una firma envolvente o separada, no se requieren transformaciones. La transformación implícita de XML-C14N se encarga de todo.
Con la actualización de seguridad introducida por el boletín de Seguridad de Microsoft MS16-035, .NET restringe las transformaciones que se pueden usar en la verificación de documentos de forma predeterminada. Las transformaciones que no son de confianza hacen CheckSignature que siempre devuelva false. En concreto, las transformaciones que requieren una entrada adicional (especificada como elementos secundarios en el XML) no se permiten debido a su susceptibilidad del abuso por parte de los usuarios malintencionados. W3C aconseja evitar las transformaciones XPath y XSLT, que son las dos transformaciones principales afectadas por estas restricciones.
El problema con las referencias externas
Si una aplicación no comprueba que las referencias externas parezcan adecuadas para el contexto actual, se pueden abusar de maneras que proporcionan muchas vulnerabilidades de seguridad (como denegación de servicio, denegación de servicio de reflexión distribuida, divulgación de información, omisión de firmas y ejecución remota de código). Incluso si una aplicación validara el URI de referencia externo, habría un problema en que el recurso se cargaba dos veces: una vez cuando la aplicación la lee y una vez cuando SignedXml la lee. Dado que no hay ninguna garantía de que los pasos de lectura y comprobación de documentos de la aplicación tengan el mismo contenido, la firma no proporciona confiabilidad.
Dados los riesgos de referencias externas, SignedXml produce una excepción cuando se encuentra una referencia externa. Para obtener más información sobre este problema, consulte .NET aplicaciones encuentran errores de excepción.
Constructores
| Nombre | Description |
|---|---|
| SignedXml() |
Inicializa una nueva instancia de la clase SignedXml. |
| SignedXml(XmlDocument) |
Inicializa una nueva instancia de la SignedXml clase a partir del documento XML especificado. |
| SignedXml(XmlElement) |
Inicializa una nueva instancia de la SignedXml clase a partir del objeto especificado XmlElement . |
Campos
| Nombre | Description |
|---|---|
| m_signature |
Representa el Signature objeto del objeto actual SignedXml . |
| m_strSigningKeyName |
Representa el nombre de la clave instalada que se va a usar para firmar el SignedXml objeto. |
| XmlDecryptionTransformUrl |
Representa el identificador uniforme de recursos (URI) para la transformación de descifrado del modo XML. Este campo es constante. |
| XmlDsigBase64TransformUrl |
Representa el identificador uniforme de recursos (URI) para la transformación base 64. Este campo es constante. |
| XmlDsigC14NTransformUrl |
Representa el identificador uniforme de recursos (URI) para la transformación XML canónico. Este campo es constante. |
| XmlDsigC14NWithCommentsTransformUrl |
Representa el identificador uniforme de recursos (URI) para la transformación XML canónico, con comentarios. Este campo es constante. |
| XmlDsigCanonicalizationUrl |
Representa el identificador uniforme de recursos (URI) para el algoritmo de canónico estándar para las firmas digitales XML. Este campo es constante. |
| XmlDsigCanonicalizationWithCommentsUrl |
Representa el identificador uniforme de recursos (URI) para el algoritmo de canónico estándar para firmas digitales XML e incluye comentarios. Este campo es constante. |
| XmlDsigDSAUrl |
Representa el identificador uniforme de recursos (URI) para el algoritmo estándar DSA para las firmas digitales XML. Este campo es constante. |
| XmlDsigEnvelopedSignatureTransformUrl |
Representa el identificador uniforme de recursos (URI) para la transformación de firma sobre. Este campo es constante. |
| XmlDsigExcC14NTransformUrl |
Representa el identificador uniforme de recursos (URI) para la canónica XML exclusiva. Este campo es constante. |
| XmlDsigExcC14NWithCommentsTransformUrl |
Representa el identificador uniforme de recursos (URI) para la canónica XML exclusiva, con comentarios. Este campo es constante. |
| XmlDsigHMACSHA1Url |
Representa el identificador uniforme de recursos (URI) para el algoritmo estándar HMACSHA1 para las firmas digitales XML. Este campo es constante. |
| XmlDsigMinimalCanonicalizationUrl |
Representa el identificador uniforme de recursos (URI) para el algoritmo de canónico mínimo estándar para las firmas digitales XML. Este campo es constante. |
| XmlDsigNamespaceUrl |
Representa el identificador uniforme de recursos (URI) del espacio de nombres estándar para las firmas digitales XML. Este campo es constante. |
| XmlDsigRSASHA1Url |
Representa el identificador uniforme de recursos (URI) para el método de firma estándar RSA para las firmas digitales XML. Este campo es constante. |
| XmlDsigRSASHA256Url |
Representa el identificador uniforme de recursos (URI) para la variación del RSA método de firma SHA-256 para las firmas digitales XML. Este campo es constante. |
| XmlDsigRSASHA384Url |
Representa el identificador uniforme de recursos (URI) para la variación del RSA método de firma SHA-384 para las firmas digitales XML. Este campo es constante. |
| XmlDsigRSASHA512Url |
Representa el identificador uniforme de recursos (URI) para la variación del RSA método de firma SHA-512 para las firmas digitales XML. Este campo es constante. |
| XmlDsigSHA1Url |
Representa el identificador uniforme de recursos (URI) para el método de resumen estándar SHA1 para las firmas digitales XML. Este campo es constante. |
| XmlDsigSHA256Url |
Representa el identificador uniforme de recursos (URI) para el método de resumen estándar SHA256 para las firmas digitales XML. Este campo es constante. |
| XmlDsigSHA384Url |
Representa el identificador uniforme de recursos (URI) para el método de resumen estándar SHA384 para las firmas digitales XML. Este campo es constante. |
| XmlDsigSHA512Url |
Representa el identificador uniforme de recursos (URI) para el método de resumen estándar SHA512 para las firmas digitales XML. Este campo es constante. |
| XmlDsigXPathTransformUrl |
Representa el identificador uniforme de recursos (URI) para el lenguaje de ruta de acceso XML (XPath). Este campo es constante. |
| XmlDsigXsltTransformUrl |
Representa el identificador uniforme de recursos (URI) para las transformaciones XSLT. Este campo es constante. |
| XmlLicenseTransformUrl |
Representa el identificador uniforme de recursos (URI) del algoritmo de transformación de licencias usado para normalizar las licencias XrML para las firmas. |
Propiedades
| Nombre | Description |
|---|---|
| EncryptedXml |
Obtiene o establece un EncryptedXml objeto que define las reglas de procesamiento de cifrado XML. |
| KeyInfo |
Obtiene o establece el KeyInfo objeto del objeto actual SignedXml . |
| Resolver |
Establece el objeto actual XmlResolver . |
| SafeCanonicalizationMethods |
Obtiene los nombres de los métodos cuyos algoritmos de canónica se permiten explícitamente. |
| Signature | |
| SignatureFormatValidator |
Obtiene un delegado al que se llamará para validar el formato (no la seguridad criptográfica) de una firma XML. |
| SignatureLength |
Obtiene la longitud de la firma del objeto actual SignedXml . |
| SignatureMethod |
Obtiene el método de firma del objeto actual SignedXml . |
| SignatureValue |
Obtiene el valor de firma del objeto actual SignedXml . |
| SignedInfo |
Obtiene el SignedInfo objeto del objeto actual SignedXml . |
| SigningKey |
Obtiene o establece la clave de algoritmo asimétrica utilizada para firmar un SignedXml objeto. |
| SigningKeyName |
Obtiene o establece el nombre de la clave instalada que se va a usar para firmar el SignedXml objeto. |
Métodos
| Nombre | Description |
|---|---|
| AddObject(DataObject) |
Agrega un DataObject objeto a la lista de objetos que se van a firmar. |
| AddReference(Reference) |
Agrega un Reference objeto al SignedXml objeto que describe un método de resumen, un valor de resumen y una transformación que se van a usar para crear una firma digital XML. |
| CheckSignature() |
Determina si la Signature propiedad comprueba el uso de la clave pública en la firma. |
| CheckSignature(AsymmetricAlgorithm) |
Determina si la Signature propiedad comprueba la clave especificada. |
| CheckSignature(KeyedHashAlgorithm) |
Determina si la Signature propiedad comprueba el algoritmo de código de autenticación de mensajes (MAC) especificado. |
| CheckSignature(X509Certificate2, Boolean) |
Determina si la Signature propiedad comprueba el objeto especificado X509Certificate2 y, opcionalmente, si el certificado es válido. |
| CheckSignatureReturningKey(AsymmetricAlgorithm) |
Determina si la Signature propiedad comprueba el uso de la clave pública en la firma. |
| ComputeSignature() |
Calcula una firma digital XML. |
| ComputeSignature(KeyedHashAlgorithm) |
Calcula una firma digital XML mediante el algoritmo de código de autenticación de mensajes (MAC) especificado. |
| Equals(Object) |
Determina si el objeto especificado es igual al objeto actual. (Heredado de Object) |
| GetHashCode() |
Actúa como función hash predeterminada. (Heredado de Object) |
| GetIdElement(XmlDocument, String) |
Devuelve el XmlElement objeto con el identificador especificado del objeto especificado XmlDocument . |
| GetPublicKey() |
Devuelve la clave pública de una firma. |
| GetType() |
Obtiene el Type de la instancia actual. (Heredado de Object) |
| GetXml() |
Devuelve la representación XML de un SignedXml objeto . |
| LoadXml(XmlElement) |
Carga un SignedXml estado de un elemento XML. |
| MemberwiseClone() |
Crea una copia superficial del Objectactual. (Heredado de Object) |
| ToString() |
Devuelve una cadena que representa el objeto actual. (Heredado de Object) |