The XMLDSIG standard defines the steps required to produce a Signature element and verify a Signature element. These steps are not very surprising, as the following subsections explain.
10.5.1 Signature Generation
Signature generation consists of two parts. First, you need to generate the Reference elements to go into SignedInfo. Second, you need to construct SignedInfo, sign it, and create the Signature element. These steps must occur in that order.
Although the XML Digital Signature standard does not require it, real-world XMLDSIG subroutine libraries will probably include an entry for generating a Manifest element as well as a Signature element. This entry would involve exactly the same Reference element generation as described here; instead of then building a Signature, however, it would wrap the References in a Manifest element with an optional application-provided Id attribute. You could then use the Manifest element as data for a higher-level Reference or Manifest element and/or include in an Object element within a Signature.
Each Reference describes one piece of data being signed. For each Reference, four steps are taken:
Obtain the raw data associated with the Reference and URI to be given. (Omit the URI if the verifier will know the URI from the application context; this omission is allowed for only one Reference in any Signature element.)
Apply any Transforms, as determined by the application, to produce the actual data signed. The result of the last Transform, or of Step 1 if no Transforms are present, should consist of a sequence of octets. If it would otherwise be an XML node-set, serialize the result with Canonical XML. If you want a different canonicalization, such as Exclusive XML Canonicalization, add it as an explicit last (or only) Transform.
Calculate the DigestValue over the data obtained in Step 2 using the application-provided DigestMethod.
Create the Reference element from the URI (if it must be specified), Transforms (if any), DigestMethod, and DigestValue.
Using the Reference elements generated earlier, generate the Signature element as follows:
Create the SignedInfo using the application-determined CanonicalizationMethod and SignatureMethod elements and the Reference elements generated earlier.
Apply the CanonicalizationMethod to the SignedInfo.
Using the application-determined signing key, apply the Signature Method to the canonicalized SignedInfo, thereby producing the SignatureValue.
Construct the Signature element using the SignedInfo element already generated, the SignatureValue, a KeyInfo element if needed, and any Object elements needed.
10.5.2 Signature Verification
Just as signature generation occurs in two phases, so signature verification takes place in two separate sets of steps. First, the Signature element is verified. Second, the Reference elements within SignedInfo inside the Signature are verified. These steps can occur in either order.
Although the XML Digital Signature standard does not require it, real-world XMLDSIG libraries will probably include an entry for validating the Reference elements in a Manifest. This validation occurs in the same way as Reference verification in SignedInfo (described later in this section), except that no explicit canonicalization takes place. Also, failure and success of individual Reference elements inside a Manifest must be reported to the application so it can decide what to do, whereas failure of any Reference within SignedInfo causes Signature verification to fail by definition.
Attempts to verify a Signature element could fail for many reasons, even if the signature is, in some sense, actually valid. For example, a particular verifier might not have implemented some optional parts of the XMLDSIG standard, it might be unable or unwilling to execute the specified algorithms or get data pointed at by a specified URI, or the actual Signature or Reference verification might fail. Subroutine libraries implementing XMLDSIG should provide different error messages for different failure conditions.
Signature verification authenticates the SignedInfo material. It requires the following steps:
Obtain the verification key using the KeyInfo element or the application context. (If KeyInfo is used to determine the key, it should be signed through a Reference in SignedInfo for greater security.)
Apply the CanonicalizationMethod to the SignedInfo and SignatureMethod elements.
Using the verification key and canonicalized SignatureMethod obtained in Step 2, verify the SignatureValue over the canonicalized SignedInfo. Sig natureValue comparisons must be done numerically or using the binary octet sequence. Do not use text comparison of base-64 encodings, because they may fail due to discrepancies in their white space conventions.
| || |
The SignatureValue elements in two different XML signatures over the same data with the same keying material and algorithms may differ due to different white space in DigestValue elements or the deliberate use of randomness for padding in algorithms.
Reference verification authenticates the data signed against the digests in SignedInfo. It requires the following steps:
Using CanonicalizationMethod, canonicalize SignedInfo. (This step isn't necessary unless a custom CanonicalizationMethod changes the Reference elements. Using such a custom CanonicalizationMethod is probably a bad idea.)
For each Reference in the canonicalized SignedInfo, do the following:
Obtain the data to be digested. Depending on the application context, you could dereference the URI attribute value and apply any Transforms, retrieve the data from a local cache, or use some other means.
Digest the data using the DigestMethod specified by the canonicalized Reference element.
Compare the result with the DigestValue in the canonicalized Reference element. If they disagree, verification for that Reference has failed. The DigestValue comparison must be done numerically or using the binary octet sequence. Do not use text comparison of base-64 encodings, because they may fail due to discrepancies in their white space conventions.