The W3C XML Signature defines XML syntax for demonstrating the authenticity of a digital message or document. If a digital signature is deemed to be a valid signature, it is highly likely that the message was created by a known sender and that the message has not been altered in transit. Therefore, XML Signatures provide a good method to detect a forgery or tampering of important XML data.
XML Signature Definition
XML Signatures are defined in the W3C recommendation XML Signature Syntax and Processing. The W3C recommendation document defines different resources that an XML signature may be applied to; this article only discusses the XML Signature in context of an enveloped signature in XML data.
An Enveloped XML signature is an XML signature that is computed over XML content that contains the signature as an element. The XML content provides a root XML document element, which contains the signature element somewhere along the XML tree. According to the W3C recommendation, the XML signature should not take itself into account when computing the signature value. Note that there is a difference between an enveloped signature as described above, and an enveloping signature. In an enveloping signature, the signature is the parent object.
XML Signature Requirements
The requirements for XML signatures can be found in the W3C working draft XML-Signature Requirements. Some important aspects of the requirements are as follows:
- XML Signatures are generated from a hash over the canonical form of a signature manifest.
- The signature manifest is a collection of references to the objects being signed.
- An XML Signature must be an XML Element.
- The XML Signature must preserve the XML Tree, except for the addition of the XML Signature Element.
Aside from enveloped XML signatures, W3C requires that detached XML signatures are possible (the signature is not part of the XML tree it is signing), but those are outside of the scope of this document.
XML Signature Syntax
XML Signatures are represented by the Signature XML element. The Signature element contains exactly one SignedInfo element, and has zero or one ID attributes. The SignedInfo element contains exactly one CanonicalizationMethod element and exactly one SignatureMethod element. The SignatureMethod element contains one or more Reference elements. Each Reference element has zero or one URI attributes. Each Reference element can contain zero or one Transforms element, and must contain exactly one DigestMethod element, and exactly one DigestValue element. The Signature element must contain exactly one SignatureValue element. The Signature element can contain zero or one KeyInfo elements, and zero or more Object elements. Each Object element has zero or one ID attributes. Note that the Object element is typically used for enveloping signatures, not enveloped signatures.
A breakdown of the XML Signature XML Tree is described by the following diagram. The following description of the above is taken from the W3C recommendation for XML Signatures. In the description “?” denotes zero or one occurrence; “+” denotes one or more occurrences; and “*” denotes zero or more occurrence.
(<Reference URI? >
XML Signature Verification
When an XML Signature is created, the SignedInfo element is the element that is actually signed. XML Signature validation requires two steps, which are as follows:
- Signature Validation – The value of the element SignatureValue must match the result of processing SignedInfo with the CanonicalizationMethod and SignatureMethod.
- Reference Validation – All content identified by a Reference object must be transformed if applicable, then processed with the specified DigestMethod. The result must match the DigestValue for that reference.
These steps can be performed in either order, but for the sake of understanding and convenience, we will delve into Reference Validation first.
Each Reference element contains zero or one URI attributes. The Schema definition for Reference elements also contains optional attributes Id and Type, but we will not consider those in this document. The URI attribute identifies a data object using a URI-Reference. The value of this attribute can be any URI, where URI syntax is dictated by RFC 3986. The URI can also be in the form of an XPointer, which is both a common and useful tool when dealing with enveloped XML Signatures.
Defining a URI with an XPointer
The XPointer is a fragment identifier for a URI described by W3C in XML Pointer Language (XPointer) Version 1.0. A fragment identifier is a short string of characters that refers to a resource that is subordinate to another resource. According to the XPointer specification version 1.0, an XPointer can act as a fragment identifier for resources with the following Internet media types:
XPointer is based on the XML Language Path (XPath) and can be used to address internal structures of XML documents. XPath is described by W3C in XML Path Language (XPath) Version 1.0.
The character “/” is used to represent the root of an XML document. Since an enveloped XML Signature is usually a Signature over the entire XML document containing the signature, it is common to see a Reference element definition such as:
<ds:Reference URI=”#xpointer(/)”>… </ds:Reference>
You’ll notice that in the previous example the Reference element has a prefix of “ds:”. This means that the XML Namespace ds contains the element Reference. XML Namespaces are described in Namespaces in XML 1.0 (Third Edition). XML Namespaces provide a way to qualify element and attribute names in XML by associating them with namespaces identified by URI resources. The use of the namespaces ds or dsig are common, but optional.
The Transforms element is optional, and contains an ordered list of Transform elements. The Transform elements describe how the data object was created before being digested. The output of each Transform serves as the input to the next Transform. The input to the first transform is the dereferenced URI attribute of the Reference element. Transform elements consist of an Algorithm attribute that specifies a URI for the algorithm. Depending on the algorithm, the content of the Transform element can provide additional data to determine how the algorithm processes the data.
A Reference element must contain a DigestMethod element. The required attribute Algorithm specifies a URI to an algorithm that is used to compute the DigestValue over the data object that is the result of the last transform. If no transforms were performed, the DigestValue is computed over the dereferenced URI of the Reference element. DigestValue is also a required element. The DigestValue element contains the encoded value of the digest. The digest is always encoded using base64.
Reference validation is the first step of core validation in XML Signature verification. W3C breaks reference validation into the following ordered steps:
- Canonicalize the SignedInfo element based on the Canonicalization Method in SignedInfo.
- For each Reference in SignedInfo:
- Obtain the data object to be digested. This involves dereferencing the Reference object’s URI and applying transforms as necessary.
- Digest the resulting data object using the DigestMethod specified in the Reference section.
- Compare the generated digest value against DigestValue in the Reference. If the generated digest does not match, validation fails.
The Signature element must contain a SignatureValue element. The SignatureValue element contains the base64 encoded signature computed over the SignedInfo element. The SignedInfo element must contain a single CanonicalizationMethod element and a single SignatureMethod element. Both the CanonicalizationMethod element and the SignatureMethod element have the required attribute Algorithm which represents a URI to the algorithm used for canonicalization and signing, respectively.
The W3C breaks signature validation into the following steps:
- Obtain the key information, either from a KeyInfo element or from an external source. Documentation for the KeyInfo element is available from W3C.
- Obtain the canonical form of the SignatureMethod using the CanonicalizationMethod and use the result (and previously obtained KeyInfo) to confirm the SignatureValue over the SignedInfo element.
After Reference validation and signature validation are completed, the XML Signature has been verified. If either of these two steps fails, the signature is not verified. Verification implies that you can be sure beyond a reasonable doubt that the xml originated from a valid source. Hopefully now you know a little more about XML Signatures. Happy Security!