SignedXml Classe
Definizione
Importante
Alcune informazioni sono relative alla release non definitiva del prodotto, che potrebbe subire modifiche significative prima della release definitiva. Microsoft non riconosce alcuna garanzia, espressa o implicita, in merito alle informazioni qui fornite.
Fornisce un wrapper in un oggetto di firma XML di base per facilitare la creazione di firme XML.
public ref class SignedXml
public class SignedXml
type SignedXml = class
Public Class SignedXml
- Ereditarietà
-
SignedXml
Esempio
Nell'esempio di codice seguente viene illustrato come firmare e verificare un intero documento XML usando una firma in busta.
//
// 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
Nell'esempio di codice seguente viene illustrato come firmare e verificare un singolo elemento di un documento XML usando una firma che avvolge.
//
// 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
Commenti
La SignedXml classe è l'implementazione .NET di World Wide Web Consortium (W3C) XML Signature Syntax and Processing Specification, nota anche come XMLDSIG (XML Digital Signature). XMLDSIG è un metodo di interoperabilità basato su standard per firmare e verificare tutto o parte di un documento XML o di altri dati indirizzabili da un URI (Uniform Resource Identifier).
Usare la SignedXml classe ogni volta che è necessario condividere dati XML firmati tra applicazioni o organizzazioni in modo standard. Tutti i dati firmati tramite questa classe possono essere verificati da qualsiasi implementazione conforme della specifica W3C per XMLDSIG.
La SignedXml classe consente di creare i tre tipi seguenti di firme digitali XML:
| Tipo di firma | Description |
|---|---|
| Firma incapsulata | La firma è contenuta all'interno dell'elemento XML firmato. |
| Firma avvolgente | Il codice XML firmato è contenuto all'interno dell'elemento <Signature> . |
| Firma disconnessa interna | La firma e il codice XML firmato si trovano nello stesso documento, ma nessuno degli elementi contiene l'altro. |
Esiste anche un quarto tipo di firma denominato firma disconnessa esterna, ovvero quando i dati e la firma si trovano in documenti XML separati. Le firme separate esterne non sono supportate dalla classe SignedXml.
Struttura di una firma XML
XMLDSIG crea un <Signature> elemento contenente una firma digitale di un documento XML o altri dati indirizzabili da un URI. L'elemento <Signature> può facoltativamente contenere informazioni sulla posizione in cui trovare una chiave che verificherà la firma e quale algoritmo di crittografia è stato usato per la firma. La struttura di base è la seguente:
<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>
Le parti principali di questa struttura sono:
Elemento
<CanonicalizationMethod>Specifica le regole per la riscrittura dell'elemento
Signatureda XML/text in byte per la convalida della firma. Il valore predefinito in .NET è http://www.w3.org/TR/2001/REC-xml-c14n-20010315, che identifica un algoritmo attendibile. Questo elemento è rappresentato dalla SignedInfo.CanonicalizationMethod proprietà .Elemento
<SignatureMethod>Specifica l'algoritmo utilizzato per la generazione e la convalida della firma, che è stato applicato all'elemento
<Signature>per produrre il valore in<SignatureValue>. Nell'esempio precedente il valore http://www.w3.org/2000/09/xmldsig#rsa-sha1 identifica una firma RSA PKCS1 SHA-1. A causa di problemi di collisione con SHA-1, Microsoft consiglia un modello di sicurezza basato su SHA-256 o superiore. Questo elemento è rappresentato dalla SignatureMethod proprietà .Elemento
<SignatureValue>Specifica la firma crittografica per l'elemento
<Signature>. Se questa firma non viene verificata, alcune parti del<Signature>blocco sono state manomesse e il documento viene considerato non valido. Purché il<CanonicalizationMethod>valore sia attendibile, questo valore è altamente resistente alle manomissioni. Questo elemento è rappresentato dalla SignatureValue proprietà .Attributo
URIdell'elemento<Reference>Specifica un oggetto dati utilizzando un riferimento URI. Questo attributo è rappresentato dalla Reference.Uri proprietà .
Non specificando l'attributo
URI, ovvero impostando la Reference.Uri proprietà sunull, significa che l'applicazione ricevente deve conoscere l'identità dell'oggetto. Nella maggior parte dei casi, unnullURI genererà un'eccezione. Non usare unnullURI, a meno che l'applicazione non interagisca con un protocollo che lo richiede.L'impostazione dell'attributo
URIsu una stringa vuota indica che l'elemento radice del documento viene firmato, una forma di firma in busta.Se il valore dell'attributo
URIinizia con #, il valore deve essere risolto in un elemento del documento corrente. Questo modulo può essere utilizzato con uno qualsiasi dei tipi di firma supportati (firma in busta, firma avvolgente o firma disconnessa interna).Qualsiasi altro elemento è considerato una firma disconnessa da una risorsa esterna e non è supportato dalla SignedXml classe .
Elemento
<Transforms>Contiene un elenco ordinato di
<Transform>elementi che descrivono come il firmatario ha ottenuto l'oggetto dati che è stato sottoposto a digestione. Un algoritmo di trasformazione è simile al metodo di canonizzazione, ma invece di riscrivere l'elemento<Signature>, riscrive il contenuto identificato dall'attributoURIdell'elemento<Reference>. L'elemento<Transforms>è rappresentato dalla TransformChain classe .Ogni algoritmo di trasformazione è definito come un processo che prevede l'uso di XML (un insieme di nodi XPath) o di byte come input. Se il formato dei dati correnti è diverso dai requisiti di input della trasformazione, vengono applicate regole di conversione.
Ogni algoritmo di trasformazione è definito come che produce XML o byte come risultato.
Se l'output dell'ultimo algoritmo di trasformazione non è definito in byte (o non sono state specificate trasformazioni), il metodo di canonizzazione viene usato come trasformazione implicita (anche se nell'elemento
<CanonicalizationMethod>è stato specificato un algoritmo diverso).Un valore di http://www.w3.org/2000/09/xmldsig#enveloped-signature per l'algoritmo di trasformazione codifica una regola che viene interpretata come rimuovere l'elemento
<Signature>dal documento. In caso contrario, un verificatore di una firma inclusa calcolerà l'hash del documento, inclusa la firma, ma il firmatario avrebbe calcolato l'hash del documento prima che la firma fosse apposta, portando a risposte diverse.
Elemento
<DigestMethod>Identifica il metodo digest (hash crittografico) da applicare al contenuto trasformato identificato dall'attributo
URIdell'elemento<Reference>. Questa proprietà è rappresentata dalla Reference.DigestMethod proprietà .
Scelta di un metodo di canonizzazione
A meno che non si stia interoperando con una specifica che richiede l'uso di un valore diverso, raccomandiamo di usare il metodo di canonizzazione .NET predefinito, cioè l'algoritmo XML-C14N versione 1.0, il cui valore è http://www.w3.org/TR/2001/REC-xml-c14n-20010315. L'algoritmo XML-C14N 1.0 deve essere supportato da tutte le implementazioni di XMLDSIG, in particolare perché è una trasformazione finale implicita da applicare.
Esistono versioni degli algoritmi di canonizzazione che supportano il mantenimento dei commenti. I metodi di canonizzazione con mantenimento dei commenti non sono consigliati perché violano il principio "firma ciò che viene visto". Ciò significa che i commenti in un <Signature> elemento non modificheranno la logica di elaborazione per la modalità di esecuzione della firma, ma solo il valore della firma. Se combinato con un algoritmo di firma debole, consentendo l'inserimento dei commenti dà a un utente malintenzionato la libertà inutile di forzare una collisione hash, rendendo legittimo un documento manomesso. In .NET Framework solo i canonizzatori predefiniti sono supportati per impostazione predefinita. Per supportare canonizzatori aggiuntivi o personalizzati, vedere la SafeCanonicalizationMethods proprietà . Se il documento usa un metodo di canonizzazione non incluso nell'insieme rappresentato dalla SafeCanonicalizationMethods proprietà , il CheckSignature metodo restituirà false.
Note
Un'applicazione estremamente difensiva può rimuovere dalla raccolta i valori che non prevede che i firmatari utilizzino SafeCanonicalizationMethods.
I valori di riferimento sono sicuri dalla manomissione?
Sì, i <Reference> valori sono sicuri da manomissioni. .NET verifica il <SignatureValue> calcolo prima di elaborare uno dei valori e delle <Reference> trasformazioni associate e interromperà in anticipo per evitare istruzioni di elaborazione potenzialmente dannose.
Scegliere gli elementi da firmare
È consigliabile usare il valore "" per l'attributo URI (o impostare la Uri proprietà su una stringa vuota), se possibile. Ciò significa che l'intero documento viene considerato per il calcolo del digest, il che significa che l'intero documento è protetto da manomissioni.
È molto comune vedere URI i valori sotto forma di ancoraggi, ad esempio #foo, facendo riferimento a un elemento il cui attributo ID è "foo". Purtroppo, è facile manometterlo perché include solo il contenuto dell'elemento di destinazione, non il contesto. L'abuso di questa distinzione è noto come XML Signature Wrapping (XSW).
Se l'applicazione considera i commenti come semantici (che non sono comuni quando si tratta di XML), è consigliabile usare "#xpointer(/)" anziché "" e "#xpointer(id('foo'))" anziché "#foo". Le versioni #xpointer vengono interpretate come includenti i commenti, mentre le forme con nomi brevi escludono i commenti.
Se è necessario accettare documenti protetti solo parzialmente e assicurarsi di leggere lo stesso contenuto protetto dalla firma, usare il GetIdElement metodo .
Considerazioni sulla sicurezza sull'elemento KeyInfo
I dati nell'elemento facoltativo <KeyInfo> , ovvero la KeyInfo proprietà , che contiene una chiave per convalidare la firma, non devono essere considerati attendibili.
In particolare, quando KeyInfo valore rappresenta una chiave pubblica RSA semplice, DSA o ECDSA, il documento potrebbe essere stato manomesso, anche se il metodo CheckSignature segnala che la firma è valida. Ciò può verificarsi perché l'entità che esegue la manomissione deve solo generare una nuova chiave e firmare nuovamente il documento manomesso con tale nuova chiave. Pertanto, a meno che l'applicazione non verifichi che la chiave pubblica sia un valore previsto, il documento deve essere considerato come se fosse stato manomesso. Ciò richiede che l'applicazione esamini la chiave pubblica incorporata all'interno del documento e la verifichi in base a un elenco di valori noti per il contesto del documento. Ad esempio, se il documento potrebbe essere riconosciuto come emesso da un utente noto, è necessario controllare la chiave in base a un elenco di chiavi note usate da tale utente.
È anche possibile verificare la chiave dopo l'elaborazione del documento usando il CheckSignatureReturningKey metodo anziché usare il CheckSignature metodo . Tuttavia, per garantire la sicurezza ottimale, è necessario verificare la chiave in anticipo.
In alternativa, provare a provare le chiavi pubbliche registrate dell'utente, invece di leggere ciò che si trova nell'elemento <KeyInfo> .
Considerazioni sulla sicurezza sull'elemento X509Data
L'elemento facoltativo <X509Data> è un elemento figlio dell'elemento <KeyInfo> e contiene uno o più certificati o identificatori X509 per i certificati X509. Anche i dati nell'elemento <X509Data> non devono essere intrinsecamente attendibili.
Quando si verifica un documento con l'elemento incorporato <X509Data> , .NET verifica solo che i dati vengano risolti in un certificato X509 la cui chiave pubblica può essere usata correttamente per convalidare la firma del documento. A differenza della chiamata al metodo CheckSignature con il parametro verifySignatureOnly impostato su false, non viene eseguito alcun controllo di revoca, non viene verificata alcuna fiducia della catena e non viene verificata alcuna scadenza. Anche se l'applicazione estrae il certificato stesso e lo passa al metodo con il CheckSignatureverifySignatureOnly parametro impostato su false, la convalida non è ancora sufficiente per evitare manomissioni del documento. Il certificato deve comunque essere verificato come appropriato per il documento firmato.
L'uso di un certificato di firma incorporato può fornire strategie utili per la rotazione delle chiavi, sia nella sezione <X509Data> che nel contenuto del documento. Quando si usa questo approccio, un'applicazione deve estrarre manualmente il certificato ed eseguire la convalida in modo simile a:
Il certificato è stato emesso direttamente o tramite una catena da un'autorità di certificazione (CA) il cui certificato pubblico è incorporato nell'applicazione.
Utilizzare l'elenco di attendibilità fornito dal sistema operativo senza controlli aggiuntivi, come il nome di un soggetto noto, non è sufficiente per evitare manomissioni in SignedXml.
Il certificato viene verificato che non sia scaduto al momento della firma del documento (o "ora" per l'elaborazione di documenti quasi in tempo reale).
Per i certificati di lunga durata rilasciati da una CA che supporta la revoca, verificare che il certificato non sia stato revocato.
L'oggetto del certificato viene verificato come appropriato per il documento corrente.
Scelta dell'algoritmo di trasformazione
Se si interagisce con una specifica che ha determinato valori specifici (ad esempio XrML), è necessario seguire la specifica. Se si dispone di una firma in busta, ad esempio quando si firma l'intero documento, è necessario usare http://www.w3.org/2000/09/xmldsig#enveloped-signature (rappresentato dalla XmlDsigEnvelopedSignatureTransform classe ). È possibile specificare anche la trasformazione implicita XML-C14N, ma non è necessaria. Per una firma avvolgente o scollegata, non sono necessarie trasformazioni. La trasformazione implicita XML-C14N si occupa di tutto.
Con l'aggiornamento della sicurezza introdotto dal bollettino Microsoft Security MS16-035, .NET limitato le trasformazioni che possono essere usate nella verifica dei documenti per impostazione predefinita. Le trasformazioni non attendibili causano CheckSignature sempre la restituzione falsedi . In particolare, le trasformazioni che richiedono input aggiuntivi (specificati come elementi figlio nel codice XML) non sono consentite a causa della loro suscettività dell'abuso da parte di utenti malintenzionati. W3C consiglia di evitare le trasformazioni XPath e XSLT, che sono le due trasformazioni principali interessate da queste restrizioni.
Problema con i riferimenti esterni
Se un'applicazione non verifica che i riferimenti esterni siano appropriati per il contesto corrente, possono essere abusati in modi che forniscono molte vulnerabilità di sicurezza (tra cui Denial of Service, Distributed Reflection Denial of Service, Divulgazione di informazioni, Bypass della firma ed Esecuzione di codice remoto). Anche se un'applicazione dovesse convalidare l'URI di riferimento esterno, rimane un problema della risorsa caricata due volte: una volta quando l'applicazione lo legge e una volta quando SignedXml lo legge. Poiché non esiste alcuna garanzia che i passaggi di lettura e verifica del documento dell'applicazione abbiano lo stesso contenuto, la firma non fornisce attendibilità.
Considerati i rischi dei riferimenti esterni, SignedXml genera un'eccezione quando viene rilevato un riferimento esterno. Per altre informazioni su questo problema, vedere .NET applicazioni riscontrano errori di eccezione.
Costruttori
| Nome | Descrizione |
|---|---|
| SignedXml() |
Inizializza una nuova istanza della classe SignedXml. |
| SignedXml(XmlDocument) |
Inizializza una nuova istanza della SignedXml classe dal documento XML specificato. |
| SignedXml(XmlElement) |
Inizializza una nuova istanza della SignedXml classe dall'oggetto specificato XmlElement . |
Campi
| Nome | Descrizione |
|---|---|
| m_signature |
Rappresenta l'oggetto Signature dell'oggetto corrente SignedXml . |
| m_strSigningKeyName |
Rappresenta il nome della chiave installata da utilizzare per firmare l'oggetto SignedXml . |
| XmlDecryptionTransformUrl |
Rappresenta l'URI (Uniform Resource Identifier) per la trasformazione decrittografia in modalità XML. Questo campo è costante. |
| XmlDsigBase64TransformUrl |
Rappresenta l'URI (Uniform Resource Identifier) per la trasformazione base 64. Questo campo è costante. |
| XmlDsigC14NTransformUrl |
Rappresenta l'URI (Uniform Resource Identifier) per la trasformazione XML canonica. Questo campo è costante. |
| XmlDsigC14NWithCommentsTransformUrl |
Rappresenta l'URI (Uniform Resource Identifier) per la trasformazione XML canonica, con commenti. Questo campo è costante. |
| XmlDsigCanonicalizationUrl |
Rappresenta l'URI (Uniform Resource Identifier) per l'algoritmo di canonizzazione standard per le firme digitali XML. Questo campo è costante. |
| XmlDsigCanonicalizationWithCommentsUrl |
Rappresenta l'URI (Uniform Resource Identifier) per l'algoritmo di canonizzazione standard per le firme digitali XML e include commenti. Questo campo è costante. |
| XmlDsigDSAUrl |
Rappresenta l'URI (Uniform Resource Identifier) per l'algoritmo standard DSA per le firme digitali XML. Questo campo è costante. |
| XmlDsigEnvelopedSignatureTransformUrl |
Rappresenta l'URI (Uniform Resource Identifier) per la trasformazione della firma in busta. Questo campo è costante. |
| XmlDsigExcC14NTransformUrl |
Rappresenta l'URI (Uniform Resource Identifier) per la canonizzazione XML esclusiva. Questo campo è costante. |
| XmlDsigExcC14NWithCommentsTransformUrl |
Rappresenta l'URI (Uniform Resource Identifier) per la canonizzazione XML esclusiva, con commenti. Questo campo è costante. |
| XmlDsigHMACSHA1Url |
Rappresenta l'URI (Uniform Resource Identifier) per l'algoritmo standard HMACSHA1 per le firme digitali XML. Questo campo è costante. |
| XmlDsigMinimalCanonicalizationUrl |
Rappresenta l'URI (Uniform Resource Identifier) per l'algoritmo di canonizzazione minimo standard per le firme digitali XML. Questo campo è costante. |
| XmlDsigNamespaceUrl |
Rappresenta l'URI (Uniform Resource Identifier) per lo spazio dei nomi standard per le firme digitali XML. Questo campo è costante. |
| XmlDsigRSASHA1Url |
Rappresenta l'URI (Uniform Resource Identifier) per il metodo di firma standard RSA per le firme digitali XML. Questo campo è costante. |
| XmlDsigRSASHA256Url |
Rappresenta l'URI (Uniform Resource Identifier) per la variante del RSA metodo di firma SHA-256 per le firme digitali XML. Questo campo è costante. |
| XmlDsigRSASHA384Url |
Rappresenta l'URI (Uniform Resource Identifier) per la variante del RSA metodo di firma SHA-384 per le firme digitali XML. Questo campo è costante. |
| XmlDsigRSASHA512Url |
Rappresenta l'URI (Uniform Resource Identifier) per la variante del RSA metodo di firma SHA-512 per le firme digitali XML. Questo campo è costante. |
| XmlDsigSHA1Url |
Rappresenta l'URI (Uniform Resource Identifier) per il metodo digest standard SHA1 per le firme digitali XML. Questo campo è costante. |
| XmlDsigSHA256Url |
Rappresenta l'URI (Uniform Resource Identifier) per il metodo digest standard SHA256 per le firme digitali XML. Questo campo è costante. |
| XmlDsigSHA384Url |
Rappresenta l'URI (Uniform Resource Identifier) per il metodo digest standard SHA384 per le firme digitali XML. Questo campo è costante. |
| XmlDsigSHA512Url |
Rappresenta l'URI (Uniform Resource Identifier) per il metodo digest standard SHA512 per le firme digitali XML. Questo campo è costante. |
| XmlDsigXPathTransformUrl |
Rappresenta l'URI (Uniform Resource Identifier) per il linguaggio XPath (XML Path Language). Questo campo è costante. |
| XmlDsigXsltTransformUrl |
Rappresenta l'URI (Uniform Resource Identifier) per le trasformazioni XSLT. Questo campo è costante. |
| XmlLicenseTransformUrl |
Rappresenta l'URI (Uniform Resource Identifier) per l'algoritmo di trasformazione delle licenze usato per normalizzare le licenze XrML per le firme. |
Proprietà
| Nome | Descrizione |
|---|---|
| EncryptedXml |
Ottiene o imposta un EncryptedXml oggetto che definisce le regole di elaborazione della crittografia XML. |
| KeyInfo |
Ottiene o imposta l'oggetto KeyInfo dell'oggetto corrente SignedXml . |
| Resolver |
Imposta l'oggetto corrente XmlResolver . |
| SafeCanonicalizationMethods |
Ottiene i nomi dei metodi i cui algoritmi di canonizzazione sono consentiti in modo esplicito. |
| Signature |
Ottiene l'oggetto Signature dell'oggetto corrente SignedXml . |
| SignatureFormatValidator |
Ottiene un delegato che verrà chiamato per convalidare il formato (non la sicurezza crittografica) di una firma XML. |
| SignatureLength |
Ottiene la lunghezza della firma per l'oggetto corrente SignedXml . |
| SignatureMethod |
Ottiene il metodo di firma dell'oggetto corrente SignedXml . |
| SignatureValue |
Ottiene il valore della firma dell'oggetto corrente SignedXml . |
| SignedInfo |
Ottiene l'oggetto SignedInfo dell'oggetto corrente SignedXml . |
| SigningKey |
Ottiene o imposta la chiave dell'algoritmo asimmetrico utilizzata per firmare un SignedXml oggetto . |
| SigningKeyName |
Ottiene o imposta il nome della chiave installata da utilizzare per firmare l'oggetto SignedXml . |
Metodi
| Nome | Descrizione |
|---|---|
| AddObject(DataObject) |
Aggiunge un DataObject oggetto all'elenco di oggetti da firmare. |
| AddReference(Reference) |
Aggiunge un Reference oggetto all'oggetto SignedXml che descrive un metodo digest, un valore digest e una trasformazione da utilizzare per la creazione di una firma digitale XML. |
| CheckSignature() |
Determina se la Signature proprietà verifica l'utilizzo della chiave pubblica nella firma. |
| CheckSignature(AsymmetricAlgorithm) |
Determina se la Signature proprietà verifica la chiave specificata. |
| CheckSignature(KeyedHashAlgorithm) |
Determina se la Signature proprietà verifica l'algoritmo MAC (Message Authentication Code) specificato. |
| CheckSignature(X509Certificate2, Boolean) |
Determina se la Signature proprietà verifica l'oggetto specificato X509Certificate2 e, facoltativamente, se il certificato è valido. |
| CheckSignatureReturningKey(AsymmetricAlgorithm) |
Determina se la Signature proprietà verifica l'utilizzo della chiave pubblica nella firma. |
| ComputeSignature() |
Calcola una firma digitale XML. |
| ComputeSignature(KeyedHashAlgorithm) |
Calcola una firma digitale XML usando l'algoritmo MAC (Message Authentication Code) specificato. |
| Equals(Object) |
Determina se l'oggetto specificato è uguale all'oggetto corrente. (Ereditato da Object) |
| GetHashCode() |
Funge da funzione hash predefinita. (Ereditato da Object) |
| GetIdElement(XmlDocument, String) |
Restituisce l'oggetto XmlElement con l'ID specificato dall'oggetto specificato XmlDocument . |
| GetPublicKey() |
Restituisce la chiave pubblica di una firma. |
| GetType() |
Ottiene il Type dell'istanza corrente. (Ereditato da Object) |
| GetXml() |
Restituisce la rappresentazione XML di un SignedXml oggetto . |
| LoadXml(XmlElement) |
Carica uno SignedXml stato da un elemento XML. |
| MemberwiseClone() |
Crea una copia superficiale del Objectcorrente. (Ereditato da Object) |
| ToString() |
Restituisce una stringa che rappresenta l'oggetto corrente. (Ereditato da Object) |