How to: Verify the Digital Signatures of XML Documents
You can use the classes in the System.Security.Cryptography.Xml namespace to verify XML data signed with a digital signature. XML digital signatures (XMLDSIG) allow you to verify that data was not altered after it was signed. For more information about the XMLDSIG standard, see the World Wide Web Consortium (W3C) specification at http://www.w3.org/TR/xmldsig-core/.
The code example in this procedure demonstrates how to verify an XML digital signature contained in a <Signature> element. The example retrieves an RSA public key from a key container and then uses the key to verify the signature.
For information about how create a digital signature that can be verified using this technique, see How to: Sign XML Documents with Digital Signatures.
To verify the digital signature of an XML document
To verify the document, you must use the same asymmetric key that was used for signing. Create a CspParameters object and specify the name of the key container that was used for signing.
Dim cspParams As New CspParameters() cspParams.KeyContainerName = "XML_DSIG_RSA_KEY"
CspParameters cspParams = new CspParameters(); cspParams.KeyContainerName = "XML_DSIG_RSA_KEY";
Retrieve the public key using the RSACryptoServiceProvider class. The key is automatically loaded from the key container by name when you pass the CspParameters object to the constructor of the RSACryptoServiceProvider class.
Dim rsaKey As New RSACryptoServiceProvider(cspParams)
RSACryptoServiceProvider rsaKey = new RSACryptoServiceProvider(cspParams);
Create an XmlDocument object by loading an XML file from disk. The XmlDocument object contains the signed XML document to verify.
Dim xmlDoc As New XmlDocument() ' Load an XML file into the XmlDocument object. xmlDoc.PreserveWhitespace = True xmlDoc.Load("test.xml")
XmlDocument xmlDoc = new XmlDocument(); // Load an XML file into the XmlDocument object. xmlDoc.PreserveWhitespace = true; xmlDoc.Load("test.xml");
Create a new SignedXml object and pass the XmlDocument object to it.
Dim signedXml As New SignedXml(Doc)
SignedXml signedXml = new SignedXml(Doc);
Find the <signature> element and create a new XmlNodeList object.
Dim nodeList As XmlNodeList = Doc.GetElementsByTagName("Signature")
XmlNodeList nodeList = Doc.GetElementsByTagName("Signature");
Load the XML of the first <signature> element into the SignedXml object.
signedXml.LoadXml(CType(nodeList(0), XmlElement))
signedXml.LoadXml((XmlElement)nodeList[0]);
Check the signature using the CheckSignature method and the RSA public key. This method returns a Boolean value that indicates success or failure.
Return signedXml.CheckSignature(Key)
return signedXml.CheckSignature(Key);
Example
This example assumes that a file named "test.xml" exists in the same directory as the compiled program. The "test.xml" file must be signed using the techniques described in How to: Sign XML Documents with Digital Signatures.
Imports System
Imports System.Security.Cryptography
Imports System.Security.Cryptography.Xml
Imports System.Xml
Module VerifyXML
Sub Main(ByVal args() As String)
Try
' Create a new CspParameters object to specify
' a key container.
Dim cspParams As New CspParameters()
cspParams.KeyContainerName = "XML_DSIG_RSA_KEY"
' Create a new RSA signing key and save it in the container.
Dim rsaKey As New RSACryptoServiceProvider(cspParams)
' Create a new XML document.
Dim xmlDoc As New XmlDocument()
' Load an XML file into the XmlDocument object.
xmlDoc.PreserveWhitespace = True
xmlDoc.Load("test.xml")
' Verify the signature of the signed XML.
Console.WriteLine("Verifying signature...")
Dim result As Boolean = VerifyXml(xmlDoc, rsaKey)
' 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 Exception
Console.WriteLine(e.Message)
End Try
End Sub
' Verify the signature of an XML file against an asymmetric
' algorithm and return the result.
Function VerifyXml(ByVal Doc As XmlDocument, ByVal Key As RSA) As [Boolean]
' Check arguments.
If Doc Is Nothing Then
Throw New ArgumentException("Doc")
End If
If Key Is Nothing Then
Throw New ArgumentException("Key")
End If
' Create a new SignedXml object and pass it
' the XML document class.
Dim signedXml As New SignedXml(Doc)
' Find the "Signature" node and create a new
' XmlNodeList object.
Dim nodeList As XmlNodeList = Doc.GetElementsByTagName("Signature")
' Throw an exception if no signature was found.
If nodeList.Count <= 0 Then
Throw New CryptographicException("Verification failed: No Signature was found in the document.")
End If
' This example only supports one signature for
' the entire XML document. Throw an exception
' if more than one signature was found.
If nodeList.Count >= 2 Then
Throw New CryptographicException("Verification failed: More that one signature was found for the document.")
End If
' Load the first <signature> node.
signedXml.LoadXml(CType(nodeList(0), XmlElement))
' Check the signature and return the result.
Return signedXml.CheckSignature(Key)
End Function
End Module
using System;
using System.Security.Cryptography;
using System.Security.Cryptography.Xml;
using System.Xml;
public class VerifyXML
{
public static void Main(String[] args)
{
try
{
// Create a new CspParameters object to specify
// a key container.
CspParameters cspParams = new CspParameters();
cspParams.KeyContainerName = "XML_DSIG_RSA_KEY";
// Create a new RSA signing key and save it in the container.
RSACryptoServiceProvider rsaKey = new RSACryptoServiceProvider(cspParams);
// Create a new XML document.
XmlDocument xmlDoc = new XmlDocument();
// Load an XML file into the XmlDocument object.
xmlDoc.PreserveWhitespace = true;
xmlDoc.Load("test.xml");
// Verify the signature of the signed XML.
Console.WriteLine("Verifying signature...");
bool result = VerifyXml(xmlDoc, rsaKey);
// 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 (Exception e)
{
Console.WriteLine(e.Message);
}
}
// Verify the signature of an XML file against an asymmetric
// algorithm and return the result.
public static Boolean VerifyXml(XmlDocument Doc, RSA Key)
{
// Check arguments.
if (Doc == null)
throw new ArgumentException("Doc");
if (Key == null)
throw new ArgumentException("Key");
// Create a new SignedXml object and pass it
// the XML document class.
SignedXml signedXml = new SignedXml(Doc);
// Find the "Signature" node and create a new
// XmlNodeList object.
XmlNodeList nodeList = Doc.GetElementsByTagName("Signature");
// Throw an exception if no signature was found.
if (nodeList.Count <= 0)
{
throw new CryptographicException("Verification failed: No Signature was found in the document.");
}
// This example only supports one signature for
// the entire XML document. Throw an exception
// if more than one signature was found.
if (nodeList.Count >= 2)
{
throw new CryptographicException("Verification failed: More that one signature was found for the document.");
}
// Load the first <signature> node.
signedXml.LoadXml((XmlElement)nodeList[0]);
// Check the signature and return the result.
return signedXml.CheckSignature(Key);
}
}
Compiling the Code
To compile this example, you need to include a reference to System.Security.dll.
Include the following namespaces: System.Xml, System.Security.Cryptography, and System.Security.Cryptography.Xml.
Security
Never store or transfer the private key of an asymmetric key pair in plaintext. For more information about symmetric and asymmetric cryptographic keys, see Generating Keys for Encryption and Decryption.
Never embed a private key directly into your source code. Embedded keys can be easily read from an assembly using the MSIL Disassembler (Ildasm.exe) or by opening the assembly in a text editor such as Notepad.
See Also
Tasks
How to: Sign XML Documents with Digital Signatures
Reference
System.Security.Cryptography.Xml