This section describes the XML digital signature syntax and discusses formal DTD and schema syntaxes as alternative descriptions of it. A certain context is assumed for the DTDs and schemas that appear in later subsections. In particular, the DTD context is assumed to be as follows: <!-- XMLDSIG DTD context --> <!-- The following entity declarations enable external/flexible content in the Signature content model. #PCDATA emulates schema:string; when combined with element types it emulates schema mixed="true". % foo.ANY permits the user to include their own element types from other namespaces, for example: <!ENTITY % KeyValue.ANY '| ecds:ECDSAKeyValue'> ... <!ELEMENT ecds:ECDSAKeyValue (#PCDATA) > --> <!ENTITY % Object.ANY ''> <!ENTITY % Method.ANY ''> <!ENTITY % Transform.ANY ''> <!ENTITY % SignatureProperty.ANY ''> <!ENTITY % KeyInfo.ANY ''> <!ENTITY % KeyValue.ANY ''> <!ENTITY % X509Data.ANY ''> <!ENTITY % PGPData.ANY ''> <!ENTITY % SPKIData.ANY ''> As explained in the comment, the entity declarations offer a way to gain extensibility. Essentially, later DTDs' (external or internal subset) ENTITY declarations can append new permitted elements if the XMLDSIG DTD is interpreted before such later DTDs. The XML schema context is assumed to be as follows: <?xml version="1.0" encoding="utf-8"?> <!-- XMLDSIG Schema context --> <!DOCTYPE schema PUBLIC "-//W3C//DTD XMLSchema 200102//EN" "http://www.w3.org/2001/XMLSchema.dtd" [ <!ATTLIST schema xmlns:ds CDATA #FIXED "http://www.w3.org/2000/09/xmldsig#"> <!ENTITY dsig 'http://www.w3.org/2000/09/xmldsig#'> <!ENTITY % p ''> <!ENTITY % s ''> ] > <schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" targetNamespace="http://www.w3.org/2000/09/xmldsig#" version="0.1" elementFormDefault="qualified">
VersioningMost signature standards include a version field in their signature structure, but XMLDSIG does not. Instead, it uses the namespaces [Names] feature of XML for this purpose. The standard defines the current XMLDSIG in the "http://www.w3.org/2000/09/xmldsig#" namespace. A new XMDSIG standard would use a new namespace. The ds:CryptoBinary Simple TypeArbitrary-length integers (e.g., "bignums") appear in XML as encoded octet strings. Schema syntax represents these using the ds:CryptoBinary simple type. Starting with such a "bignum," you first convert the integer to a "big endian" bit sequence. You then pad the bit sequence with leading zero bits so that the total length is a multiple of 8. Next, you remove any leading octets that are zero, so that the high-order octet is always nonzero. This sequence is then base-64 [RFC 2045] encoded. (The conversion from integer to octet string is equivalent to the PKCS#1's I2OSP [RFC 2437] with minimal length.) "Bignum" values such as RSAKeyValue and DSAKeyValue use this type. If a value can be of type base64Binary or ds:CryptoBinary, it is specified as base64Binary. For example, if the signature algorithm is RSA or DSA, then SignatureValue represents a bignum and could be ds:CryptoBinary. If HMAC-SHA1 is the signature algorithm, however, SignatureValue is a fixed-size binary quantity where leading zero bytes should be preserved. For this reason, SignatureValue is specified to be of type base64Binary. Following is the schema for ds:CryptoBinary: <!-- CryptoBinary Schema --> <simpleType name="CryptoBinary"> <restriction base="base64Binary"/> </simpleType> DTDs have a much cruder concept of data type than XML schemas, and CryptoBinary is not used in them. AlgorithmsSix elements that specify algorithms can appear as descendants of the Signature element: CanonicalizationMethod, SignatureMethod, DigestMethod, Transform, and, within a KeyInfo type element, AgreementMethod and EncryptionMethod. For more details on algorithms, see Chapter 17. URI RepresentationXML Security uses URI [RFC 2396] attribute values in several places. For example, it uses attribute values to identify algorithms in algorithm role elements, to point to data in Reference elements, and to identify data types in Reference and RetrievalMethod elements. You need to take care when encoding URIs as attribute values, as explained in Chapter 7. 10.2.1 The Signature ElementLet's look at the structure of the XMLDSIG element. Example 10-1 provides a skeletal XML version of just about the simplest possible Signature element. (See the preface for a description of skeletal XML.) Example 10-1 Skeletal Signature element<Signature> <!-- simplified skeletal Signature element--> <SignedInfo> (CanonicalizationMethod) (SignatureMethod) <Reference> (DigestMethod) (DigestValue) </Reference> </SignedInfo> (SignatureValue) </Signature> Although this example is very simple, we can see a few things. Inside the Signature element, we have the actual SignatureValue and SignedInfo. Inside SignedInfo we have a SignatureMethod and a Reference. The Reference specifies the data we are signing. The DigestMethod algorithm digests the data, and the resulting DigestValue appears inside the Reference element. A digest of data is analogous to a unique fingerprint calculated from and representing the data (see Chapter 2). It is also usually much shorter than the data. For all practical purposes, then, signing the digest is as good as signing the original data. The verifier can verify the signature on the digest, check whether the digest corresponds to the data, and consider the signature verified on the data. Signature Element SyntaxThe actual DTD syntax of the Signature element is as follows: <!-- Signature DTD --> <!ELEMENT Signature (SignedInfo, SignatureValue, KeyInfo?, Object*) > <!ATTLIST Signature xmlns CDATA #FIXED 'http://www.w3.org/2000/09/xmldsig#' Id ID #IMPLIED > In schema notation, it has the following form: <!-- Signature Schema --> <element name="Signature" type="ds:SignatureType"/> <complexType name="SignatureType"> <sequence> <element ref="ds:SignedInfo"/> <element ref="ds:SignatureValue"/> <element ref="ds:KeyInfo" minOccurs="0"/> <element ref="ds:Object" minOccurs="0" maxOccurs="unbounded"/> </sequence> <attribute name="Id" type="ID" use="optional"/> </complexType> 10.2.2 The SignedInfo ElementThe most complex parts of an XML digital signature are usually the SignedInfo element and the KeyInfo element. They provide information on the data and the key for the signature, respectively. SignedInfo is described follows; Chapter 13 describes KeyInfo. The SignedInfo element DTD syntax is as follows: <!-- SignedInfo DTD --> <!ELEMENT SignedInfo (CanonicalizationMethod, SignatureMethod, Reference+) > <!ATTLIST SignedInfo Id ID #IMPLIED > In schema notation, it has the following form: <!-- SignedInfo Schema --> <element name="SignedInfo" type="ds:SignedInfoType"/> <complexType name="SignedInfoType"> <sequence> <element ref="ds:CanonicalizationMethod"/> <element ref="ds:SignatureMethod"/> <element ref="ds:Reference" maxOccurs="unbounded"/> </sequence> <attribute name="Id" type="ID" use="optional"/> </complexType> During signature verification, the SignedInfo element bundles together the following items:
The following subsections discuss each of these elements. The CanonicalizationMethod ElementModern signature algorithms operate on a sequence of eight-bit bytes or octets. SignedInfo is, of course, XML that has been read into or constructed by an application. It must be converted to a sequence of octets so that it can be signed using the SignatureMethod algorithm. The XML standard requires that much of the external surface representation of SignedInfo be thrown away, as it is read in, and not given to that application. Even so, the signature verification application must use the same sequence of octets for SignedInfo that the signing application uses. The CanonicalizationMethod converts SignedInfo into a sequence of octets. Standard XML canonicalizations have been developed that handle the most common canonicalization requirements of XML, as discussed in Chapter 9. The way in which you present the SignedInfo to the canonicalization method depends on that method.
For resource-constrained applications that do not implement XML canonicalization but rather use a text canonicalization, the standard recommends that they be implemented to generate canonicalized XML as their output serialization. This approach will mitigate interoperability and security concerns.
Consider the following example CanonicalizationMethod: <CanonicalizationMethod Algorithm="http://www.w3.org/TR/xml-exc-c14n"/> The value of the Algorithm attribute specifies the algorithm; its implicit input is SignedInfo. You can specify any needed explicit parameters as element content (see Chapter 17).
The syntax for the CanonicalizationMethod element is as follows: <!-- CanonicalizationMethod DTD --> <!ELEMENT CanonicalizationMethod (#PCDATA %Method.ANY;)* > <!ATTLIST CanonicalizationMethod Algorithm CDATA #REQUIRED > In schema notation, it has the following form: <!-- CanonicalizationMethod schema --> <element name="CanonicalizationMethod" type="ds:CanonicalizationMethodType"/> <complexType name="CanonicalizationMethodType" mixed="true"> <sequence> <any namespace="##any" minOccurs="0" maxOccurs="unbounded"/> <!-- (0,unbounded) elements from (1,1) namespace --> </sequence> <attribute name="Algorithm" type="anyURI" use="required"/> </complexType> The SignatureMethod ElementThe SignatureMethod element specifies the algorithm that is applied to the canonicalized SignedInfo and the signing key, as implicit inputs, to produce the SignatureValue as its output. An example of a SignatureMethod element is as follows: <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/> The syntax for SignatureMethod is as follows: <!-- SignatureMethod DTD --> <!ELEMENT SignatureMethod (#PCDATA | HMACOutputLength %Method.ANY;)* > <!ATTLIST SignatureMethod Algorithm CDATA #REQUIRED > In schema notation, it has the following form: <!-- SignatureMethod schema --> <element name="SignatureMethod" type="ds:SignatureMethodType"/> <complexType name="SignatureMethodType" mixed="true"> <sequence> <element name="HMACOutputLength" minOccurs="0" type="ds:HMACOutputLengthType"/> <any namespace="##other" minOccurs="0" maxOccurs="unbounded"/> <!-- (0,unbounded) elements from (1,1) external namespace --> </sequence> <attribute name="Algorithm" type="anyURI" use="required"/> </complexType> 10.2.3 The Reference ElementReference elements in SignedInfo specify which data is being signed. At least one Reference element must appear in SignedInfo, but there can be more. The syntax for each Reference is as follows: <!-- Reference DTD --> <!ELEMENT Reference (Transforms?, DigestMethod, DigestValue) > <!ATTLIST Reference Id ID #IMPLIED URI CDATA #IMPLIED Type CDATA #IMPLIED > In schema notation, it has the following form: <!-- Reference schema --> <element name="Reference" type="ds:ReferenceType"/> <complexType name="ReferenceType"> <sequence> <element ref="ds:Transforms" minOccurs="0"/> <element ref="ds:DigestMethod"/> <element ref="ds:DigestValue"/> </sequence> <attribute name="Id" type="ID" use="optional"/> <attribute name="URI" type="anyURI" use="optional"/> <attribute name="Type" type="anyURI" use="optional"/> </complexType> The optional Id attribute makes it easier to point to the Reference from elsewhere. The attribute named URI, if present, must have a URI [RFC 2396] as its value. It is considered optional because sometimes you can determine the location of a data item to be signed from the application context without any explicit pointer. To avoid confusion, you can omit the URI attribute on only one Reference within a SignedInfo. XMLDSIG applications must be able to parse Uniform Resource Identifier (URI) syntax, as specified in Chapter 7. The standard recommends that XMLDSIG applications support the "http:" access scheme. Retrieval based on an "http:" URI must comply with redirect status codes that may be returned. If multiple URIs of different levels of specificity exist for the same resource, you should use the most specific one to minimize the chance of the signature or application breaking because it receives a different version of the data. For example, the first of the following two URIs is preferred: http://www.w3.org/2000/06/interop-pressrelease.html.en http://www.w3.org/2000/06/interop-pressrelease The optional Type attribute, if present, also has a URI [RFC 2396] value that represents the type of the data to which the Reference applies. The Type has no effect on Signature verification as defined in XMLDSIG but might be used by other processing. For example, in some application context, Manifest elements (Section 10.2.7) might need special processing. If, in that application, the Type attribute is always present for Manifest element data, the program could use it to decide whether to specially retrieve and process that data. The Type attribute applies to the item being pointed at, not its contents. For example, a reference that points to an Object element containing a SignatureProperties element is still of type "http://www.w3.org/2000/09/xmldsig#Object." On the other hand, a pointer that points directly to that same SignatureProperties element should identify it as of type "http://www.w3.org/2000/09/xmldsig#SignatureProperties." The XMLDSIG standard considers the Type information advisory and requires no validation of it. The Transforms ElementTransforms provide a powerful mechanism to indicate processing of the data before they are digested. You might want to extract a subset of the data, for example, if that is all you want to sign. Transforms are part of a data pipeline starting from retrieval, going through possible transform operations, and ending with the DigestMethod, are discussed in Section 10.4. The DigestMethod ElementDigestMethod is a required element in a Reference that identifies the digest algorithm to be applied to the signed data. This element uses the standard algorithm syntax described in Chapter 17. If the result of the data fetch and application of Transforms is an XPath node-set (or sufficiently functional replacement implemented by the application), then the application must convert it to a sequence of octets on which the DigestMethod can operate (see Section 10.4). If the data fetch and application of Transforms results in an octet stream, then no conversion is needed. The application applies the digest algorithm to the resulting octet stream. The syntax for DigestMethod is as follows: <!-- DigestMethod DTD --> <!ELEMENT DigestMethod (#PCDATA %Method.ANY;)* > <!ATTLIST DigestMethod Algorithm CDATA #REQUIRED > In schema notation, it has the following form: <!-- DigestMethod schema --> <element name="DigestMethod" type="ds:DigestMethodType"/> <complexType name="DigestMethodType" mixed="true"> <sequence> <any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/> </sequence> <attribute name="Algorithm" type="anyURI" use="required"/> </complexType> The DigestValue ElementThe DigestValue is a mandatory element in Reference that contains the encoded value of the digest output from DigestMethod. The digest is always encoded in base-64 [RFC 2045]. The syntax for DigestMethod is as follows: <!-- DigestValue DTD --> <!ELEMENT DigestValue (#PCDATA) > <!-- base64 encoded digest value --> In schema notation, it has the following form: <!-- DigestValue schema --> <element name="DigestValue" type="ds:DigestValueType"/> <simpleType name="DigestValueType"> <restriction base="base64Binary"/> </simpleType> Reference ExamplesExample 10-2 shows a simplified enveloping signature data Reference, where "foo" [RFC 3092] is the ID of a signed XML element included in an Object element later in the signature. Example 10-2 Enveloping Reference element<Reference URI="#foo"> <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/> <DigestValue>qZk+NkcGgWq6PiVxeFDCbJzQ2J0=</DigestValue> </Reference> Example 10-3 shows a simplified enveloped signature Reference where the null URI refers to the entire document containing this Reference. Here, the enveloped-signature transform exempts the signature from trying to cover itself. Example 10-3 Enveloped Reference element<Reference URI=""> <Transforms><Transform Algorithm= "http://www.w3.org/2000/09/xmldsig#enveloped-signature"/> </Transforms> <DigestMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#md5"/> <DigestValue>qZk+NkcGgWq6PiVxeFDCbJ==</DigestValue> </Reference> Example 10-4 shows a detached signature where it is assumed that the file referenced by the URI contains base-64 encoded data. The signature covers the decode of that data, and the Reference element itself can be referred to conveniently by its ID. Example 10-4 Detached Reference element<Reference URI="ftp://foo.example/bar.b64"> <Transforms> <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#base64"/> </Transforms> <DigestMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#md5"/> <DigestValue>qZk+NkcGgWq6PiVxeFDCbJ==</DigestValue> </Reference> 10.2.4 The SignatureValue ElementThe SignatureValue element stores the actual binary signature value. This value is calculated over the canonicalized SignedInfo using SignatureMethod and the signing key. The value is encoded as base-64. The syntax of the SignatureValue element is as follows: <!-- SignatureValue DTD --> <!ELEMENT SignatureValue (#PCDATA) > <!ATTLIST SignatureValue Id ID #IMPLIED> In schema notation, it has the following form: <!-- SignatureValue schema --> <element name="SignatureValue" type="ds:SignatureValueType"/> <complexType name="SignatureValueType"> <simpleContent> <extension base="ds:base64Binary"> <attribute name="Id" type="ID" use="optional"/> </extension> </simpleContent> </complexType> 10.2.5 The KeyInfo ElementThe KeyInfo element provides information to help the verifier find the appropriate verification key. Chapter 13 describes this element, which is used for both signatures and encryption. 10.2.6 The Object ElementThe Object element provides a convenient envelope for putting data inside a Signature element but outside SignedInfo. It provides a convenient way to give the MIME type of the data [RFC 2045], such as "text/html" or "image/gif," and its encoding. Binary objects will normally be encoded in base-64. Object is an optional element that may occur multiple times. While Signature provides for Object elements to appear only in a specific place within it, applications can use Object outside of Signature if desired. Example 10-5 demonstrates use of the Object element. Example 10-5 Object element<Signature> <SignedInfo> ... </SignedInfo> <Object Encoding="http://www.w3.org/2000/09/xmldsig#base64" MimeType="image/jpeg"> W1OWlgjBwUSmppX3... </Object> </Signature> The Object element syntax is as follows: <!-- Object DTD --> <!ELEMENT Object (#PCDATA|Signature|SignatureProperties|Manifest %Object.ANY;)* > <!ATTLIST Object Id ID #IMPLIED MimeType CDATA #IMPLIED Encoding CDATA #IMPLIED > In schema notation, it has the following form: <!-- Object schema --> <element name="Object" type="ds:ObjectType"/> <complexType name="ObjectType" mixed="true"> <sequence minOccurs="0" maxOccurs="unbounded"> <any namespace="##any" processContents="lax"/> </sequence> <attribute name="Id" type="ID" use="optional"/> <attribute name="MimeType" type="string" use="optional"/> <attribute name="Encoding" type="anyURI" use="optional"/> </complexType> The Id attribute provides a convenient way of referencing the Object from elsewhere for example, from a Reference in SignedInfo or from a Manifest. The MimeType attribute is purely advisory, and the signature standard requires no checking of this attribute. Applications that require strong control of type and encoding for signature verification should probably specify Transforms that produce the type and encoding they want. If an application wants to exclude the start and end tags of Object from digest calculation, a Reference must identify the actual data inside the Object element. This task may be easy to perform for XML data inside Object if it has an ID. For non-XML text data, the program must use a Transform to remove the Object tags. Exclusion of the object tags would be necessary in a case where the signature must remain valid if the data object moves from inside a signature to outside the signature (or vice versa), or if the content of the Object is an encoding of an original binary document and you want to extract and decode it so as to sign the original representation.
10.2.7 The Manifest ElementA Manifest element closely resembles a SignedInfo except that it contains only References and the application has control over what happens if verification of the DigestValue in some References fails. You could use Manifest elements to advantage in the following cases, if you have access to this optional feature:
The syntax for the Manifest element is as follows: <!-- Manifest DTD --> <!ELEMENT Manifest (Reference+) > <!ATTLIST Manifest Id ID #IMPLIED > In schema notation, it has the following form: <!-- Manifest schema --> <element name="Manifest" type="ds:ManifestType"/> <complexType name="ManifestType"> <sequence> <element ref="ds:Reference" maxOccurs="unbounded"/> </sequence> <attribute name="Id" type="ID" use="optional"/> </complexType> The optional Id attribute is one way to reference a Manifest element from a Reference element or another Manifest element. 10.2.8 The SignatureProperties ElementThe SignatureProperties element holds additional information relevant to the Signature itself or cryptographic parts of it such as a DigestValue. Examples of such information would be the time of calculation or the serial number of a hardware device used in the calculation. The syntax of SignatureProperties is as follows: <!-- SignatureProperties DTD --> <!ELEMENT SignatureProperties (SignatureProperty+) > <!ATTLIST SignatureProperties Id ID #IMPLIED > <!ELEMENT SignatureProperty (#PCDATA %SignatureProperty.ANY;)* > <!ATTLIST SignatureProperty Target CDATA #REQUIRED Id ID #IMPLIED > In schema notation, it has the following form: <!-- SignatureProperties Schema --> <element name="SignatureProperties" type="ds:SignaturePropertiesType"/> <complexType name="SignaturePropertiesType"> <sequence> <element ref="ds:SignatureProperty" maxOccurs="unbounded"/> </sequence> <attribute name="Id" type="ID" use="optional"/> </complexType> <element name="SignatureProperty" type="ds:SignaturePropertyType"/> <complexType name="SignaturePropertyType" mixed="true"> <choice maxOccurs="unbounded"> <any namespace="##other" processContents="lax"/> <!-- (1,1) elements from (1,unbounded) namespaces --> </choice> <attribute name="Target" type="anyURI" use="required"/> <attribute name="Id" type="ID" use="optional"/> </complexType> Note that the required Target attribute in SignatureProperty points to the element to which the property applies. It will usually be the Id of a Signature or Reference element.
10.2.9 Comments and Processing InstructionsXML comments and processing instructions are not used by and have no special significance in Signature elements or any of the elements defined in this chapter. If you use Exclusive XML Canonicalization or Canonical XML for your CanonicalizationMethod, you can freely add and delete comments from the SignedInfo element without affecting the signature. Standard canoni calizations do not automatically eliminate processing instructions, so messing with them will likely break signatures. Similarly, if you do not canonicalize away comments within SignedInfo or signed XML, signatures will be sensitive to changes in comments. |