How to: Sign XML Documents with Digital Signatures
You can use the classes in the System.Security.Cryptography.Xml namespace to sign an XML document or part of an XML document 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 digitally sign an entire XML document and attach the signature to the document in a <Signature> element. The example creates an RSA signing key, adds the key to a secure key container, and then uses the key to digitally sign an XML document. The key can then be retrieved to verify the XML digital signature, or be used to sign another XML document.
For information about how to verify an XML digital signature that was created using this procedure, see How to: Verify the Digital Signatures of XML Documents.
To digitally sign an XML document
Create a CspParameters object and specify the name of the key container.
Dim cspParams As New CspParameters() cspParams.KeyContainerName = "XML_DSIG_RSA_KEY"
CspParameters cspParams = new CspParameters(); cspParams.KeyContainerName = "XML_DSIG_RSA_KEY";
Generate a symmetric key using the RSACryptoServiceProvider class. The key is automatically saved to the key container when you pass the CspParameters object to the constructor of the RSACryptoServiceProvider class. This key will be used to sign the XML document.
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 XML element to encrypt.
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);
Add the signing RSA key to the SignedXml object.
signedXml.SigningKey = Key
signedXml.SigningKey = Key;
Create a Reference object that describes what to sign. To sign the entire document, set the Uri property to
""
.' Create a reference to be signed. Dim reference As New Reference() reference.Uri = ""
// Create a reference to be signed. Reference reference = new Reference(); reference.Uri = "";
Add an XmlDsigEnvelopedSignatureTransform object to the Reference object. A transformation allows the verifier to represent the XML data in the identical manner that the signer used. XML data can be represented in different ways, so this step is vital to verification.
Dim env As New XmlDsigEnvelopedSignatureTransform() reference.AddTransform(env)
XmlDsigEnvelopedSignatureTransform env = new XmlDsigEnvelopedSignatureTransform(); reference.AddTransform(env);
Add the Reference object to the SignedXml object.
signedXml.AddReference(reference)
signedXml.AddReference(reference);
Compute the signature by calling the ComputeSignature method.
signedXml.ComputeSignature()
signedXml.ComputeSignature();
Retrieve the XML representation of the signature (a <Signature> element) and save it to a new XmlElement object.
Dim xmlDigitalSignature As XmlElement = signedXml.GetXml()
XmlElement xmlDigitalSignature = signedXml.GetXml();
Append the element to the XmlDocument object.
Doc.DocumentElement.AppendChild(Doc.ImportNode(xmlDigitalSignature, True))
Doc.DocumentElement.AppendChild(Doc.ImportNode(xmlDigitalSignature, true));
Save the document.
xmlDoc.Save("test.xml")
xmlDoc.Save("test.xml");
Example
Imports System
Imports System.Security.Cryptography
Imports System.Security.Cryptography.Xml
Imports System.Xml
Module SignXML
Sub Main(ByVal args() As String)
Try
' Create a new CspParameters object to specify
' a key container.
Dim cspParams As New CspParameters()
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")
' Sign the XML document.
SignXml(xmlDoc, rsaKey)
Console.WriteLine("XML file signed.")
' Save the document.
xmlDoc.Save("test.xml")
Catch e As Exception
Console.WriteLine(e.Message)
End Try
End Sub
' Sign an XML file.
' This document cannot be verified unless the verifying
' code has the key with which it was signed.
Sub SignXml(ByVal Doc As XmlDocument, ByVal Key As RSA)
' 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 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))
End Sub
End Module
using System;
using System.Security.Cryptography;
using System.Security.Cryptography.Xml;
using System.Xml;
public class SignXML
{
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");
// Sign the XML document.
SignXml(xmlDoc, rsaKey);
Console.WriteLine("XML file signed.");
// Save the document.
xmlDoc.Save("test.xml");
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
// Sign an XML file.
// This document cannot be verified unless the verifying
// code has the key with which it was signed.
public static void SignXml(XmlDocument Doc, RSA Key)
{
// Check arguments.
if (Doc == null)
throw new ArgumentException("Doc");
if (Key == null)
throw new ArgumentException("Key");
// 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));
}
}
This example assumes that a file named "test.xml"
exists in the same directory as the compiled program. You can place the following XML into a file called test.xml
and use it with this example.
<root>
<creditcard>
<number>19834209</number>
<expiry>02/02/2002</expiry>
</creditcard>
</root>
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: Verify the Digital Signatures of XML Documents
Reference
System.Security.Cryptography.Xml