The .NET Framework supports
the XML
Signature specification (commonly referred to as XMLDSIG), which
provides a standard approach to creating and representing signatures
for XML documents.
In this section, we introduce the .NET XMLDSIG classes. We do not
discuss all of the options available to you or provide in-depth
coverage of the standard itself. The XMLDSIG standard is complex, and
full coverage is outside the scope of this book. For full details of
the XML Signature specification, consult the World Wide Web
Consortium web site, at http://www.w3.org/TR/xmldsig-core. Consult
the .NET documentation for full details of the XMLDSIG classes. You
should have a basic understanding of how the .NET Framework supports
XML.
1. XMLDSIG Explained
The .NET Framework includes
classes
that support creating and verifying XMLDSIG signatures for XML
documents; in other words, the .NET XMLDSIG classes allow you to sign
XML documents to create signatures that are also XML documents
themselves.
Throughout this section, we will base our examples on creating a
signature for the following simple XML, which we assume is in a file
named book.xml:
<book>
<title>Programming .NET Security</title>
<author>Adam Freeman</author>
<author>Allen Jones</author>
</book>
All of the .NET XMLDSIG classes are contained in the
System.Security.Cryptography.Xml namespace, which
is included in System.Security.dll.
2. Signing an XML Document
In the following sections, we demonstrate
how to create an XMLDSIG signature for
our sample XML document.
2.1. Creating the reference
To create a signature, the first
step is to
create a reference to the XML document that you want to sign. The
.NET Reference class allows you to create a
reference using a URL string or a stream of data. When the signature
is created, the XML data will be read from the URL or the stream to
create the signature. The following statements demonstrate how to
create a Reference object:
# C#
// specify the URL of the document we want to sign
string x_url = "http://www.mydomain.com/book.xml";
// create a reference that points to the URL
Reference x_url_ref = new Reference(x_url);
// open a file stream for the document we want to sign
FileStream x_stream = new FileStream("book.xml", FileMode.Open);
// create a Reference that will use the stream
Reference x_stream_ref = new Reference(x_stream);
# Visual Basic .NET
' specify the URL of the document we want to sign
Dim x_url As String = "http:'www.mydomain.com/book.xml"
' create a reference that points to the URL
Dim x_url_ref As Reference = New Reference(x_url)
' open a file stream for the document we want to sign
Dim x_stream As FileStream = New FileStream("book.xml", FileMode.Open)
' create a Reference that will use the stream
Dim x_stream_ref As Reference = New Reference(x_stream)
2.2. Creating the SignedXML
The System.Security.Cryptography.Xml.SignedXml
class is responsible for creating the signature document. Create an
instance of this class, and then
configure it with the settings you wish to use in creating the
signature. Create a new instance of the SignedXml
class using the default constructor, and then use the
AddReferenceReference object you created in the previous
section:
method to add the
# C#
SignedXml x_signed_xml = new SignedXml( );
x_signed_xml.AddReference(x_stream_ref);
# Visual Basic .NET
Dim x_signed_xml As SignedXml = New SignedXml( )
x_signed_xml.AddReference(x_stream_ref)
2.3. Setting the signing algorithm
you need to create a new asymmetric signing
algorithm instance and assign it to the SignedXml
object using the SigningKey property, as
illustrated by the following statements:
# C#
// create a new instance of the DSA algorithm
DSA x_dsa = DSA.Create( );
// configure the signing key
// ...
// set the algorithm for the SignedXml
x_signed_xml.SigningKey = x_dsa;
# Visual Basic .NET
' create a new instance of the DSA algorithm
Dim x_dsa As DSA = DSA.Create( )
' configure the signing key
' ...
' set the algorithm for the SignedXml
x_signed_xml.SigningKey = x_dsa
These statements have the effect of defining the algorithm and the
keys that will be used to create the signature. The .NET classes
support using the RSA and DSA algorithms for generating XML Signature
documents.
2.4. Creating the signature
Create the signature by calling the
ComputeSignature method. You can then obtain the
signature by calling the GetXml method, and obtain
a string representation by using the OuterXml
property, as shown below:
# C#
x_signed_xml.ComputeSignature( );
Console.WriteLine(x_signed_xml.GetXml( ).OuterXml);
# Visual Basic .NET
x_signed_xml.ComputeSignature( )
Console.WriteLine(x_signed_xml.GetXml( ).OuterXml)
The result of creating a DSA signature for our sample XML is as
follows:
<Signature xmlns="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#dsa-sha1" />
<Reference>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
<DigestValue>eJgWGA+lXiqrOpXa+2NSBbO1HS4=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>u5zleIl7IY5MV8sxsirlGIqRaZ9LgExoKdQwgCMqaPxWZX7VOAcT9g==
</SignatureValue>
</Signature>
Notice that the XML signature document contains information about the
signing algorithm (DSA), the hashing algorithm (SHA-1), and the
signature value, which has been Base64-encoded. This is a formalized
representation of the information that is needed to verify the
signature, which would otherwise have to be communicated between
parties in an ad hoc manner (for example, Alice and Bob exchange
messages to agree on the hashing and signing algorithms before they
exchange signed data).