RFC 3075

XML-Signature Syntax and Processing

๐Ÿ“… published March 2001, from ietf

RFC 3075: XML-Signature Syntax and Processing ๐ŸŽ€

Part 1 of 13, so more is coming! โœจ

Okay bestie, this is RFC 3075, and it's a Standards Track doc from March 2001 ๐Ÿ’…. The authors are D. Eastlake (Motorola), J. Reagle (W3C/MIT), and D. Solo (Citigroup). The header has no Obsoletes or Updates lines, so it isn't replacing or patching any older RFC ๐Ÿฆ‹.


Status of this Memo

Okay so this doc is an Internet standards track protocol for the Internet community, and it's asking for discussion and suggestions for improvements ๐ŸŒธ. If you want to know where this protocol stands in the standardization process, check the current edition of the "Internet Official Protocol Standards" (STD 1) ๐Ÿ“‹. And good news: distribution of this memo is unlimited ๐Ÿ’œ.

Copyright (c) 2001 The Internet Society & W3C (MIT, INRIA, Keio), All Rights Reserved. ๐Ÿ”’

Abstract

Okay, the abstract is basically the whole vibe โœจ. This document lays out the rules and syntax for XML digital signature processing (XML = Extensible Markup Language). XML Signatures give you integrity, message authentication, and/or signer authentication for data of any type ๐Ÿ’–. That data can live inside the XML that holds the signature, or somewhere else entirely. Iconic. ๐Ÿ‘‘

Table of Contents

1.  Introduction ................................................  3
      1. Editorial Conventions ..................................  3
      2. Design Philosophy ......................................  4
      3. Versions, Namespaces and Identifiers ...................  4
      4. Acknowledgements .......................................  5
2.  Signature Overview and Examples .............................  6
      1. Simple Example (Signature, SignedInfo, Methods, and
         References) ............................................  7
           1. More on Reference .................................  9
      2. Extended Example (Object and SignatureProperty) ........ 10
      3. Extended Example (Object and Manifest) ................. 11
3.  Processing Rules ............................................ 13
      1. Core Generation .... ................................... 13
           1. Reference Generation .............................. 13
           2. Signature Generation .............................. 13

      2. Core Validation ........................................ 13
           1. Reference Validation .............................. 14
           2. Signature Validation .............................. 14
4.  Core Signature Syntax ....................................... 14
      1. The Signature element .................................. 15
      2. The SignatureValue Element ............................. 16
      3. The SignedInfo Element ................................. 16
           1. The CanonicalizationMethod Element ................ 17
           2. The SignatureMethod Element ....................... 18
           3. The Reference Element ............................. 19
                1. The URI Attribute ............................ 19
                2. The Reference Processing Model ............... 21
                3. Same-Document URI-References ................. 23
                4. The Transforms Element ....................... 24
                5. The DigestMethod Element ..................... 25
                6. The DigestValue Element ...................... 26
      4. The KeyInfo Element .................................... 26
           1. The KeyName Element ............................... 27
           2. The KeyValue Element .............................. 28
           3. The RetrievalMethod Element ....................... 28
           4. The X509Data Element .............................. 29
           5. The PGPData Element ............................... 31
           6. The SPKIData Element .............................. 32
           7. The MgmtData Element .............................. 32
      5. The Object Element ..................................... 33
5.  Additional Signature Syntax ................................. 34
      1. The Manifest Element ................................... 34
      2. The SignatureProperties Element ........................ 35
      3. Processing Instructions ................................ 36
      4. Comments in dsig Elements .............................. 36
6.  Algorithms .................................................. 36
      1. Algorithm Identifiers and Implementation Requirements .. 36
      2. Message Digests ........................................ 38
           1. SHA-1 ............................................. 38
      3. Message Authentication Codes ........................... 38
           1. HMAC .............................................. 38
      4. Signature Algorithms ................................... 39
           1. DSA ............................................... 39
           2. PKCS1 ............................................. 40
      5. Canonicalization Algorithms ............................ 42
           1. Minimal Canonicalization .......................... 43
           2. Canonical XML ..................................... 43
      6. Transform Algorithms ................................... 44
           1. Canonicalization .................................. 44
           2. Base64 ............................................ 44
           3. XPath Filtering ................................... 45
           4. Enveloped Signature Transform ..................... 48
           5. XSLT Transform .................................... 48

7.  XML Canonicalization and Syntax Constraint Considerations ... 49
      1. XML 1.0, Syntax Constraints, and Canonicalization  ..... 50
      2. DOM/SAX Processing and Canonicalization ................ 51
8.  Security Considerations ..................................... 52
      1. Transforms ............................................. 52
           1. Only What is Signed is Secure ..................... 52
           2. Only What is "Seen" Should be Signed .............. 53
           3. "See" What is Signed .............................. 53
      2. Check the Security Model ............................... 54
      3. Algorithms, Key Lengths, Etc. .......................... 54
9.  Schema, DTD, Data Model,and Valid Examples .................. 55
10. Definitions ................................................. 56
11. References .................................................. 58
12. Authors' Addresses .......................................... 63
13. Full Copyright Statement .................................... 64

1.0 Introduction โœจ

Okay so this section sets the scene ๐ŸŽฌ. It defines the XML syntax and processing rules for making and representing digital signatures. XML Signatures can wrap up any digital content (a data object), XML included ๐Ÿ’…. One XML Signature can cover the content of one or more resources ๐Ÿงš.

There are two main flavors. Enveloped or enveloping signatures cover data inside the same XML document as the signature. Detached signatures cover data outside the signature element ๐Ÿฆ‹. The spec defines two things: an XML signature element type, and an XML signature application. Conformance requirements for the element type come through schema definitions, and conformance requirements for the application come through prose ๐Ÿ“œ. It also includes other useful types for referencing collections of resources, algorithms, and keying and management information ๐ŸŒˆ.

The XML Signature is a way of linking a key to referenced data (octets) ๐Ÿ”‘. It does not normatively say how keys get tied to people or institutions, and it doesn't say what the referenced and signed data means ๐Ÿ™ˆ. So even though this spec is an important piece of secure XML apps, it's not enough on its own to handle every application security or trust concern. That's especially true when you're using signed XML (or other data formats) as the basis for human-to-human communication and agreement ๐Ÿ’€. An application has to specify its own key, algorithm, processing, and rendering requirements. For more, check out Security Considerations (section 8) ๐Ÿซถ.

Lowkey the big takeaway: a valid signature doesn't automatically mean the signed thing is trustworthy for humans. Your app has to add that part itself ๐Ÿ’–.

1.1 Editorial and Conformance Conventions

Okay, for readability, brevity, and historic reasons, this doc uses the word "signature" to mean digital authentication values of all types ๐ŸŒธ. Strictly speaking, though, "signature" is for authentication values based on public keys that give you signer authentication ๐Ÿ”. When we're talking about authentication values based on symmetric secret key codes, we switch to the terms authenticators or authentication codes ๐ŸŽ€. (See Check the Security Model, section 8.3.)

This spec uses both XML Schemas [XML-schema] and DTDs [XML]. If DTD syntax is new to you, Ron Bourret's "Declaring Elements and Attributes in an XML DTD" [Bourret] is a great read ๐Ÿ“š. The schema definition is the normative one right now โœจ.

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this spec are to be read as described in RFC2119 [KEYWORDS]. Here's the rule from that RFC, which is honestly iconic ๐Ÿ‘‘:

"they MUST only be used where it is actually required for interoperation or to limit behavior which has potential for causing harm (e.g., limiting retransmissions)"

So we use these capitalized keywords to clearly spell out requirements for protocol and application features and behavior that affect interoperability and security ๐Ÿ’…. We don't use them in capitals to describe XML grammar. The schema definitions already describe those requirements unambiguously, and we want to save the big-attention caps for the natural language parts of the protocols and features ๐Ÿ’–. For example, an XML attribute might be described as being "optional." ๐Ÿงš And compliance with the XML-namespace specification [XML-ns] is described as "REQUIRED." ๐ŸŽ€

1.2 Design Philosophy

The design philosophy and requirements for this spec live in the XML-Signature Requirements document [XML-Signature-RD] ๐ŸŒˆ. Go check it out if you want the why behind all of this ๐Ÿฆ‹.


1.3 Versions, Namespaces and Identifiers โœจ

okay so there's no explicit version number in this syntax ๐Ÿ’… if a future version ever happens, it's gonna use a different namespace instead, which is honestly so smart. the XML namespace [XML-ns] URI that MUST be used by implementations of this (dated) specification is:

xmlns="http://www.w3.org/2000/09/xmldsig#"

this namespace is also the prefix for the algorithm identifiers ๐ŸŽ€ ngl applications MUST support XML and XML-namespaces, but internal entities [XML], our "dsig" XML namespace prefix, and the defaulting/scoping conventions are OPTIONAL. we only use them to make the examples compact and readable ๐Ÿซถ

This specification uses Uniform Resource Identifiers [URI] to identify resources, algorithms, and semantics โœจ the URI in the namespace declaration above also serves as a prefix for URIs under this spec's control. for resources that aren't under our control, we use the Uniform Resource Names [URN] or Uniform Resource Locators [URL] defined by their own normative external specification. and if an external spec hasn't given itself a URI, we allocate one under our own namespace. for example:

SignatureProperties is identified and defined by this specification's
      namespace
      http://www.w3.org/2000/09/xmldsig#SignatureProperties
XSLT is identified and defined by an external URI
      http://www.w3.org/TR/1999/PR-xslt-19991008
SHA1 is identified via this specification's namespace and defined via
      a normative reference
      http://www.w3.org/2000/09/xmldsig#sha1
      FIPS PUB 180-1.  Secure Hash Standard.  U.S. Department of
      Commerce/National Institute of Standards and Technology.

last thing, for terse namespace declarations we sometimes use XML internal entities [XML] inside URIs ๐Ÿงš like this:

<?xml version='1.0'?>
<!DOCTYPE Signature SYSTEM
  "xmldsig-core-schema.dtd" [ <!ENTITY dsig
  "http://www.w3.org/2000/09/xmldsig#"> ]>
<Signature xmlns="&dsig;" Id="MyFirstSignature">
  <SignedInfo>
  ...

1.4 Acknowledgements ๐ŸŒธ

the working group members below all helped shape this spec, and we're so grateful ๐Ÿฅน

  • Mark Bartel, JetForm Corporation (Author)
  • John Boyer, PureEdge (Author)
  • Mariano P. Consens, University of Waterloo
  • John Cowan, Reuters Health
  • Donald Eastlake 3rd, Motorola (Chair, Author/Editor)
  • Barb Fox, Microsoft (Author)
  • Christian Geuer-Pollmann, University Siegen
  • Tom Gindin, IBM
  • Phillip Hallam-Baker, VeriSign Inc
  • Richard Himes, US Courts
  • Merlin Hughes, Baltimore
  • Gregor Karlinger, IAIK TU Graz
  • Brian LaMacchia, Microsoft
  • Peter Lipp, IAIK TU Graz
  • Joseph Reagle, W3C (Chair, Author/Editor)
  • Ed Simon, Entrust Technologies Inc. (Author)
  • David Solo, Citigroup (Author/Editor)
  • Petteri Stenius, DONE Information, Ltd
  • Raghavan Srinivas, Sun
  • Kent Tamura, IBM
  • Winchel Todd Vincent III, GSU
  • Carl Wallace, Corsec Security, Inc.
  • Greg Whitehead, Signio Inc.

and a big thank-you to the last call commenters too ๐Ÿ’œ

  • Dan Connolly, W3C
  • Paul Biron, Kaiser Permanente, on behalf of the XML Schema WG.
  • Martin J. Duerst, W3C; and Masahiro Sekiguchi, Fujitsu; on behalf of the Internationalization WG/IG.
  • Jonathan Marsh, Microsoft, on behalf of the Extensible Stylesheet Language WG.

2.0 Signature Overview and Examples ๐Ÿ”ฅ

this section is the overview with examples of the XML digital signature syntax ๐Ÿ‘‘ the detailed processing lives in Processing Rules (section 3), and the formal syntax is in Core Signature Syntax (section 4) and Additional Signature Syntax (section 5).

here we use an informal representation and examples to show the structure of the signature syntax. just know that this might leave out some attributes, details, and features that get fully explained later ๐Ÿ™ˆ

okay so XML Signatures get applied to arbitrary digital content (data objects) through an indirection ๐Ÿฆ‹ the data objects get digested, the result goes into an element along with other info, and then that element gets digested and cryptographically signed. XML digital signatures are represented by the Signature element, which looks like this ("?" means zero or one occurrence, "+" means one or more, and "*" means zero or more):

<Signature>
  <SignedInfo>
    (CanonicalizationMethod)
    (SignatureMethod)
    (<Reference (URI=)? >
      (Transforms)?
      (DigestMethod)
      (DigestValue)
    </Reference>)+
  </SignedInfo>
  (SignatureValue)
 (KeyInfo)?
 (Object)*
</Signature>

signatures link to data objects via URIs [URI] ๐ŸŒˆ inside an XML document, signatures point at local data objects with fragment identifiers. that local data can be included inside an enveloping signature, or it can enclose an enveloped signature. detached signatures cover external network resources or local data objects that live in the same XML document as sibling elements. so the signature is neither enveloping (signature is parent) nor enveloped (signature is child) ๐Ÿ’– and since a Signature element (and its Id attribute value/name) can coexist or be combined with other elements (and their IDs) in one XML document, be careful when you pick names so you don't get collisions that break the ID uniqueness validity constraint [XML] ๐Ÿ˜ญ

2.1 Simple Example (Signature, SignedInfo, Methods, and References) ๐Ÿงš

this one's a detached signature of the content of the HTML4 in XML specification, and it's giving clean ๐Ÿ“

[s01] <Signature Id="MyFirstSignature"
       xmlns="http://www.w3.org/2000/09/xmldsig#">
[s02]   <SignedInfo>
[s03]   <CanonicalizationMethod
         Algorithm="http://www.w3.org/TR/2000/CR-xml-c14n-20001026"/>
[s04]   <SignatureMethod
         Algorithm="http://www.w3.org/2000/09/xmldsig#dsa-sha1"/>
[s05]   <Reference URI="http://www.w3.org/TR/2000/REC-xhtml1-20000126/">
[s06]     <Transforms>
[s07]       <Transform Algorithm="http://www.w3.org/TR/2000/
             CR-xml-c14n-20001026"/>

[s08]     </Transforms>
[s09]     <DigestMethod Algorithm="http://www.w3.org/2000/09/
           xmldsig#sha1"/>
[s10]     <DigestValue>j6lwx3rvEPO0vKtMup4NbeVu8nk=</DigestValue>
[s11]   </Reference>
[s12] </SignedInfo>
[s13]   <SignatureValue>MC0CFFrVLtRlk=...</SignatureValue>
[s14]   <KeyInfo>
[s15a]    <KeyValue>
[s15b]      <DSAKeyValue>
[s15c]        <P>...</P><Q>...</Q><G>...</G><Y>...</Y>
[s15d]      </DSAKeyValue>
[s15e]    </KeyValue>
[s16]   </KeyInfo>
[s17] </Signature>

[s02-12] the SignedInfo element is the required part, and it's the info that actually gets signed ๐Ÿซถ core validation of SignedInfo has two mandatory processes: validating the signature over SignedInfo, and validating each Reference digest inside SignedInfo. also, the algorithms used to compute the SignatureValue are included in the signed info too, even though the SignatureValue element sits outside SignedInfo ๐Ÿ”

[s03] the CanonicalizationMethod is the algorithm used to canonicalize SignedInfo before it gets digested as part of the signature operation ๐Ÿ’…

[s04] the SignatureMethod is the algorithm that turns the canonicalized SignedInfo into the SignatureValue โœจ it's a mix of a digest algorithm and a key-dependent algorithm, plus maybe other stuff like padding, for example RSA-SHA1. the algorithm names get signed so nobody can swap in a weaker algorithm and get away with it ๐Ÿšซ for app interoperability, we specify a set of signature algorithms that MUST be implemented, even though the signature creator decides whether to actually use them. we also list additional algorithms as RECOMMENDED or OPTIONAL to implement, and the signature design lets people specify their own algorithms too ๐ŸŒŸ

[s05-11] each Reference element includes the digest method and the resulting digest value, computed over the identified data object. it can also include the transforms that produced the input to the digest operation ๐Ÿฆ‹ a data object gets signed by computing its digest value, then signing that value. the signature gets checked later through reference and signature validation โœ…

[s14-16] KeyInfo tells you which key to use to validate the signature ๐Ÿ”‘ possible forms include certificates, key names, and key agreement algorithms and info (we only define a few of those). KeyInfo is optional for two reasons ๐Ÿ™ƒ first, the signer might not want to reveal key info to every document processing party. second, the info might already be known from the application's context, so it doesn't need to be represented explicitly. KeyInfo sits outside SignedInfo, so if the signer wants to bind the keying info to the signature, a Reference can point at the KeyInfo and include it as part of the signature ๐Ÿ’œ

2.1.1 More on Reference ๐Ÿ’…

[s05]   <Reference URI="http://www.w3.org/TR/2000/REC-xhtml1-20000126/">
[s06]     <Transforms>
[s07]       <Transform
             Algorithm="http://www.w3.org/TR/2000/
             CR-xml-c14n-20001026"/>
[s08]     </Transforms>
[s09]     <DigestMethod Algorithm="http://www.w3.org/2000/09/
           xmldsig#sha1"/>
[s10]     <DigestValue>j6lwx3rvEPO0vKtMup4NbeVu8nk=</DigestValue>
[s11]   </Reference>

[s05] the URI attribute on Reference is optional, and it names the data object to be signed ๐ŸŽ€ it can be left out on at most one Reference in a Signature. (this limit exists so that references and objects can always be matched up unambiguously ๐Ÿ™ˆ)

[s05-08] this identification, together with the transforms, is the signer's own description of how they got the signed data object into the form that was digested, meaning the digested content ๐Ÿ“ the verifier can get the digested content some other way, as long as the digest verifies โœจ specifically, the verifier can pull the content from a different location, like a local store, instead of the one in the URI.

[s06-08] Transforms is an optional, ordered list of processing steps applied to the resource's content before it's digested ๐Ÿงš transforms can include things like canonicalization, encoding/decoding (including compression/inflation), XSLT, and XPath ๐Ÿ’– XPath transforms let the signer derive an XML document that leaves out parts of the source document. because of that, those excluded parts can change without breaking the signature's validity ๐Ÿ™ƒ for example, if the signed resource encloses the signature itself, you have to use a transform like that to exclude the signature value from its own computation ๐ŸŒˆ if there's no Transforms element, the resource's content gets digested directly. we specify mandatory (and optional) canonicalization and decoding algorithms, and user-specified transforms are allowed too ๐Ÿ‘‘

[s09-10] DigestMethod is the algorithm applied to the data after Transforms runs (if there are any) to produce the DigestValue ๐Ÿ”ฅ signing the DigestValue is what binds a resource's content to the signer's key. that's the whole flex ๐Ÿ’…โœจ

2.2 Extended Example (Object and SignatureProperty) ๐ŸŽ€

okay bestie, quick vibe check: this spec does NOT do statements or assertions ๐Ÿ™…โ€โ™€๏ธ what it does do is define what it means for something to be signed by an XML Signature (message authentication, integrity, and/or signer authentication) ๐Ÿ” if an app wants other semantics, it has to lean on other tech like [XML, RDF] ๐Ÿ“š for example, an app could slap a foo:assuredby attribute in its own markup to point at a Signature element ๐Ÿ’… which means the app is the one that has to understand it and make the trust calls, based on whether the signature is valid and what assuredby actually means ๐Ÿง  (main character app energy, honestly).

We also define a SignatureProperties element type ๐Ÿฆ‹ for putting assertions about the signature itself in there, like signature semantics, the time of signing, or the serial number of the hardware doing the crypto โฐ๐Ÿ”ง. You can sign those assertions too, by including a Reference for the SignatureProperties in SignedInfo ๐Ÿซถ. Signing apps, be careful what you sign!! ๐Ÿ˜ญ you gotta understand what's in the SignatureProperty. Receiving apps have zero obligation to understand that semantic ๐Ÿคทโ€โ™€๏ธ (though the parent trust engine might want to ๐Ÿ‘€). Any content about how the signature was generated can live inside the SignatureProperty element ๐ŸŒธ. And the Target attribute is mandatory ๐Ÿ’œ it points at the Signature element the property applies to.

Consider the example above, but with an extra reference to a local Object that holds a SignatureProperty element โœจ. (This one would be detached [p02] AND enveloping [p03] ๐Ÿ™ˆ double threat.)

[   ]  <Signature Id="MySecondSignature" ...>
[p01]  <SignedInfo>
[   ]   ...
[p02]   <Reference URI="http://www.w3.org/TR/xml-stylesheet/">
[   ]   ...
[p03]   <Reference URI="#AMadeUpTimeStamp"
[p04]         Type="http://www.w3.org/2000/09/
                    xmldsig#SignatureProperties">
[p05]    <DigestMethod Algorithm="http://www.w3.org/2000/09/
          xmldsig#sha1"/>
[p06]    <DigestValue>k3453rvEPO0vKtMup4NbeVu8nk=</DigestValue>
[p07]   </Reference>
[p08]  </SignedInfo>
[p09]  ...
[p10]  <Object>
[p11]   <SignatureProperties>
[p12]     <SignatureProperty Id="AMadeUpTimeStamp"
           Target="#MySecondSignature">
[p13]        <timestamp xmlns="http://www.ietf.org/rfc3075.txt">
[p14]          <date>19990908</date>
[p15]          <time>14:34:34:34</time>
[p16]        </timestamp>
[p17]     </SignatureProperty>
[p18]   </SignatureProperties>
[p19]  </Object>
[p20]</Signature>

okay so the optional Type attribute on Reference tells you about the resource the URI points to ๐ŸŽฏ it can say it's an Object, a SignatureProperty, or a Manifest element ๐Ÿงฉ apps can use that to kick off special processing for certain References. References to an XML data element inside an Object element SHOULD identify the actual element pointed to ๐Ÿ’–. If the content isn't XML (maybe it's binary or encoded data), the reference should identify the Object instead, and if a Type is given, it SHOULD indicate Object ๐ŸŒˆ. Heads up though: Type is advisory ๐Ÿ™ƒ core behaviour doesn't need any action based on it, or any checking of whether it's correct ๐Ÿ’€.

Object is an optional element for stuffing data objects inside the signature element (or somewhere else) ๐Ÿ“. It can be typed and/or encoded, optionally ๐Ÿซง.

Signature properties, like time of signing, can optionally be signed by pointing to them from a Reference โœ๏ธ (people traditionally call these signature "attributes", even though that word has nothing to do with the XML term "attribute" ๐Ÿ™ƒ total naming mix-up).


2.3 Extended Example (Object and Manifest) ๐Ÿ“ฆ

The Manifest element exists to cover extra needs that the mandatory parts of this spec don't handle directly ๐Ÿงƒ. There are two needs, and here's how the Manifest handles each one:

First, apps often need to efficiently sign loads of data objects, even when the signature operation itself is an expensive public key signature ๐Ÿ’ธ. You can do this by putting multiple Reference elements in SignedInfo, since each digest secures the data it covers โœ…. But some apps don't want the core validation that comes with that, because it forces every Reference in SignedInfo through reference validation (the DigestValue elements get checked) ๐Ÿ˜ค. Those apps might want to keep the reference validation decision logic for themselves ๐Ÿ‘‘. Like, an app might get a signature-valid SignedInfo with three Reference elements. If one Reference fails (the data object doesn't digest to the specified DigestValue), the signature fails core validation ๐Ÿ’”. But the app might want to treat the signature over the two valid References as valid, or do different things depending on which one failed ๐Ÿค”. So SignedInfo references a Manifest element that holds one or more Reference elements (same structure as the ones in SignedInfo) ๐Ÿงฉ, and then reference validation of the Manifest is under the app's control ๐Ÿ’….

Second, picture many signatures (using different keys) applied to a big pile of documents ๐Ÿ“š. The inefficient move is a separate signature per key over a big SignedInfo (with lots of References), over and over ๐Ÿ˜ต that's wasteful and redundant. The better move is to put lots of references into one Manifest, then reference that Manifest from multiple Signature elements ๐ŸŽ‰.

The example below has a Reference that signs a Manifest found inside the Object element ๐Ÿ‘‡

[   ] ...
[m01]   <Reference URI="#MyFirstManifest"
[m02]     Type="http://www.w3.org/2000/09/xmldsig#Manifest">
[m03]     <DigestMethod Algorithm="http://www.w3.org/2000/09/
           xmldsig#sha1"/>
[m04]     <DigestValue>345x3rvEPO0vKtMup4NbeVu8nk=</DigestValue>
[m05]   </Reference>
[   ] ...
[m06] <Object>
[m07]   <Manifest Id="MyFirstManifest">
[m08]     <Reference>
[m09]     ...
[m10]     </Reference>
[m11]     <Reference>
[m12]     ...
[m13]     </Reference>
[m14]   </Manifest>
[m15] </Object>

3.0 Processing Rules โš™๏ธ

okay, this section is the step-by-step for signature generation and validation ๐Ÿ› ๏ธ bestie, read it slowly.

3.1 Core Generation ๐Ÿ—๏ธ

The REQUIRED steps cover generating the Reference elements and the SignatureValue over SignedInfo ๐Ÿ’–.

3.1.1 Reference Generation

Here's the drill for each data object being signed:

  1. Apply the Transforms (the application decides which ones) to the data object.
  2. Calculate the digest value over the resulting data object.
  3. Create a Reference element, with the (optional) identification of the data object, any (optional) transform elements, the digest algorithm, and the DigestValue.

3.1.2 Signature Generation

  1. Create the SignedInfo element with SignatureMethod, CanonicalizationMethod and Reference(s).
  2. Canonicalize, then calculate the SignatureValue over SignedInfo based on the algorithms specified in SignedInfo.
  3. Construct the Signature element, which includes SignedInfo, Object(s) (if desired; the encoding can be different from what was used for signing), KeyInfo (if required), and SignatureValue ๐Ÿง.

3.2 Core Validation ๐Ÿ”

The REQUIRED steps of core validation are (1) reference validation, which checks the digest in each Reference in SignedInfo, and (2) cryptographic signature validation of the signature calculated over SignedInfo.

Note, there may be valid signatures that some signature applications can't validate ๐Ÿ˜ฌ. Reasons include failing to implement optional parts of this spec, being unable or unwilling to run the specified algorithms, or being unable or unwilling to dereference the specified URIs (some URI schemes can cause nasty side effects) ๐Ÿ’€, and so on.

3.2.1 Reference Validation

For each Reference in SignedInfo:

  1. Canonicalize the SignedInfo element based on the CanonicalizationMethod in SignedInfo.
  2. Obtain the data object to be digested. (The signature application may rely on the identification (URI) and Transforms the signer provided in the Reference element, or it may get the content through other means, like a local cache ๐Ÿ—‚๏ธ.)
  3. Digest the resulting data object using the DigestMethod specified in its Reference specification.
  4. Compare the generated digest value against the DigestValue in the SignedInfo Reference. If there's any mismatch, validation fails ๐Ÿšซ.

Note, SignedInfo is canonicalized in step 1 so the application "Sees What is Signed" ๐Ÿ‘€, which is the canonical form. For instance, if the CanonicalizationMethod rewrote URIs (e.g., absolutizing relative URIs), signature processing has to be aware of that.

3.2.2 Signature Validation

  1. Obtain the keying information from KeyInfo or from an external source ๐Ÿ”‘.
  2. Obtain the canonical form of the SignatureMethod using the CanonicalizationMethod, and use the result (plus the KeyInfo you already got) to validate the SignatureValue over the SignedInfo element.

Note, KeyInfo (or some transformed version of it) may be signed via a Reference element. Transforming and validating that reference (3.2.1) is totally separate from Signature Validation, which uses KeyInfo as parsed ๐Ÿงฉ.

Additionally, the SignatureMethod URI may have been altered by canonicalization of SignedInfo (e.g., absolutization of relative URIs), and it is the canonical form that MUST be used. However, the required canonicalization [XML-C14N] of this specification does not change URIs ๐Ÿ™Œ.


4.0 Core Signature Syntax ๐Ÿ“œ

The general structure of an XML signature is described in Signature Overview (section 2). This section gives the detailed syntax of the core signature features. Features described here are mandatory to implement unless otherwise indicated ๐Ÿ’…. The syntax is defined via DTDs and [XML-Schema], with the following XML preamble, declaration, internal entity, and simpleType:

Schema Definition:

<!DOCTYPE schema
   PUBLIC "-//W3C//DTD XMLSCHEMA 200010//EN"
          "http://www.w3.org/2000/10/XMLSchema.dtd"
  [
   <!ATTLIST schema
     xmlns:ds CDATA #FIXED "http://www.w3.org/2000/09/xmldsig#">
   <!ENTITY dsig 'http://www.w3.org/2000/09/xmldsig#'>
  ]>
<schema xmlns="http://www.w3.org/2000/10/XMLSchema"
      xmlns:ds="&dsig;"
      targetNamespace="&dsig;"
      version="0.1"
      elementFormDefault="qualified">

<!-- Basic Types Defined for Signatures -->

<simpleType name="CryptoBinary">
  <restriction base="binary">
   <encoding value="base64"/>
  </restriction>
</simpleType>

DTD:

<!-- These entity declarations permit the flexible parts of Signature
     content model to be easily expanded -->

<!ENTITY % Object.ANY '(#PCDATA|Signature|SignatureProperties|
                        Manifest)*'>
<!ENTITY % Method.ANY '(#PCDATA|HMACOutputLength)*'>
<!ENTITY % Transform.ANY '(#PCDATA|XPath|XSLT)'>
<!ENTITY % SignatureProperty.ANY '(#PCDATA)*'>
<!ENTITY % Key.ANY '(#PCDATA|KeyName|KeyValue|RetrievalMethod|
           X509Data|PGPData|MgmtData|DSAKeyValue|RSAKeyValue)*'>

4.1 The Signature element ๐ŸŒŸ

The Signature element is the root element of an XML Signature. Signature elements MUST be laxly schema valid [XML-schema] with respect to the following schema definition:

Schema Definition:

<element name="Signature">
  <complexType>
    <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>
</element>

DTD:

<!ELEMENT Signature (SignedInfo, SignatureValue, KeyInfo?, Object*)  >
<!ATTLIST Signature
          xmlns  CDATA   #FIXED 'http://www.w3.org/2000/09/xmldsig#'
          Id     ID  #IMPLIED >

4.2 The SignatureValue Element ๐Ÿ’–

The SignatureValue element holds the actual value of the digital signature โœจ, and it is always encoded using base64 [MIME]. We specify a mandatory set and an optional-to-implement set of SignatureMethod algorithms ๐Ÿ’…, but user specified algorithms are permitted ๐Ÿซถ. Schema Definition:

<element name="SignatureValue" type="ds:CryptoBinary"/>

DTD:

<!ELEMENT SignatureValue (#PCDATA) >

4.3 The SignedInfo Element ๐Ÿฆ‹

SignedInfo is the element that brings together the canonicalization algorithm, a signature algorithm, and one or more references ๐ŸŒธ. It may contain an optional ID attribute, which lets other signatures and objects reference it. Main character energy ๐Ÿ‘‘

SignedInfo does not include explicit signature or digest properties, like calculation time or a cryptographic device serial number ๐Ÿ™ˆ. If an application needs to attach properties to the signature or digest, it may put that info in a SignatureProperties element inside an Object element ๐Ÿงš. Schema Definition:

<element name="SignedInfo">
  <complexType>
    <sequence>
      <element ref="ds:CanonicalizationMethod"/>
      <element ref="ds:SignatureMethod"/>
      <element ref="ds:Reference" maxOccurs="unbounded"/>
    </sequence>

  <attribute name="Id" type="ID" use="optional"/>
  </complexType>
</element>

DTD:

<!ELEMENT SignedInfo (CanonicalizationMethod,
       SignatureMethod,  Reference+)  >
<!ATTLIST SignedInfo
       Id  ID      #IMPLIED>

4.3.1 The CanonicalizationMethod Element ๐Ÿ“

Okay so CanonicalizationMethod is a required element ๐ŸŽ€ that says which canonicalization algorithm gets applied to SignedInfo before any signature math happens. It uses the general algorithm structure from Algorithm Identifiers and Implementation Requirements (section 6.1). Implementations MUST support the REQUIRED Canonical XML [XML-C14N] method ๐Ÿ˜ญ โœจ.

Alternatives to the REQUIRED Canonical XML algorithm (section 6.5.2), like Canonical XML with Comments (section 6.5.2) and Minimal Canonicalization (the CRLF and charset normalization specified in section 6.5.1), may be explicitly specified ๐Ÿ’œ but are NOT REQUIRED. So their use may not interoperate with other applications that do no support the specified algorithm (see XML Canonicalization and Syntax Constraint Considerations, section 7). Security issues may also show up in entity processing and comments if minimal or other non-XML aware canonicalization algorithms are not properly constrained (see section 8.2: Only What is "Seen" Should be Signed) ๐Ÿ’€ this is the part to be careful with, bestie ๐Ÿšจ.

The way SignedInfo gets handed to the canonicalization method depends on that method ๐ŸŒˆ. Here's how it works for the two types of algorithms in this document:

  • Canonical XML [XML-C14N] (with or without comments) implementation MUST be provided with an XPath node-set originally formed from the document containing the SignedInfo and currently indicating the SignedInfo, its descendants, and the attribute and namespace nodes of SignedInfo and its descendant elements (such that the namespace context and similar ancestor information of the SignedInfo is preserved).
  • Minimal canonicalization implementations MUST be provided with the octets that represent the well-formed SignedInfo element, from the first character to the last character of the XML representation, inclusive. This includes the entire text of the start and end tags of the SignedInfo element as well as all descendant markup and character data (i.e., the text) between those tags.

We RECOMMEND that resource constrained applications that do not implement the Canonical XML [XML-C14N] algorithm and instead choose minimal canonicalization (or some other form) be implemented to generate Canonical XML as their output serialization ๐Ÿซถ, so they can easily mitigate some of these interoperability and security concerns. (While a result might not be the canonical form of the original, it can still be in canonical form.) For instance, such an implementation SHOULD (at least) generate standalone XML instances [XML] โœจ.

Schema Definition:

<element name="CanonicalizationMethod">
  <complexType>
    <sequence>
      <any namespace="##any" minOccurs="0" maxOccurs="unbounded"/>
    </sequence>
    <attribute name="Algorithm" type="uriReference" use="required"/>
  </complexType>
</element>

DTD:

<!ELEMENT CanonicalizationMethod %Method.ANY; >
<!ATTLIST CanonicalizationMethod
          Algorithm CDATA #REQUIRED >

4.3.2 The SignatureMethod Element ๐Ÿ”ฅ

SignatureMethod is a required element ๐ŸŽ€ that specifies the algorithm used for signature generation and validation. This algorithm identifies all the cryptographic functions involved in the signature operation (e.g., hashing, public key algorithms, MACs, padding, etc.) ๐Ÿงš. This element uses the general structure here for algorithms described in section 6.1: Algorithm Identifiers and Implementation Requirements. While there is a single identifier, that identifier may specify a format containing multiple distinct signature values ๐Ÿฆ‹.

Schema Definition:

<element name="SignatureMethod">
  <complexType>
    <sequence>
      <any namespace="##any" minOccurs="0" maxOccurs="unbounded"/>
    </sequence>
    <attribute name="Algorithm" type="uriReference" use="required"/>
   </complexType>

</element>

DTD:

<!ELEMENT SignatureMethod %Method.ANY; >
<!ATTLIST SignatureMethod
          Algorithm CDATA #REQUIRED >

4.3.3 The Reference Element ๐ŸŒธ

Reference is an element that may occur one or more times ๐Ÿ’…. It specifies a digest algorithm and digest value, and optionally an identifier of the object being signed, the type of the object, and/or a list of transforms to be applied prior to digesting. The identification (URI) and transforms describe how the digested content (i.e., the input to the digest method) was created. The Type attribute helps with processing referenced data. For example, while this specification makes no requirements over external data, an application may wish to signal that the referent is a Manifest ๐Ÿ‘‘. An optional ID attribute lets a Reference be referenced from elsewhere โœจ.

Schema Definition:

<element name="Reference">
  <complexType>
    <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="uriReference" use="optional"/>
    <attribute name="Type" type="uriReference" use="optional"/>
  </complexType>
</element>

DTD:

<!ELEMENT Reference (Transforms?, DigestMethod, DigestValue)  >
<!ATTLIST Reference
          Id     ID  #IMPLIED
          URI    CDATA   #IMPLIED
          Type   CDATA   #IMPLIED >

4.3.3.1 The URI Attribute ๐Ÿฆ‹

The URI attribute identifies a data object using a URI-Reference, as specified by RFC2396 [URI]. The set of allowed characters for URI attributes is the same as for XML, namely [Unicode]. However, some Unicode characters are disallowed from URI references ๐Ÿ™ˆ, including all non-ASCII characters and the excluded characters listed in RFC2396 [URI, section 2.4]. However, the number sign (#), percent sign (%), and square bracket characters re-allowed in RFC 2732 [URI-Literal] are permitted. Disallowed characters must be escaped as follows:

  1. Each disallowed character is converted to [UTF-8] as one or more bytes.
  2. Any octets corresponding to a disallowed character are escaped with the URI escaping mechanism (that is, converted to %HH, where HH is the hexadecimal notation of the byte value).
  3. The original character is replaced by the resulting character sequence.

XML signature applications MUST be able to parse URI syntax ๐Ÿ’–. We RECOMMEND they be able to dereference URIs in the HTTP scheme ๐ŸŒˆ. Dereferencing a URI in the HTTP scheme MUST comply with the Status Code Definitions of [HTTP] (e.g., 302, 305 and 307 redirects are followed to obtain the entity-body of a 200 status code response) ๐Ÿ”ฅ. Applications should also be cognizant of the fact that protocol parameter and state information (such as HTTP cookies, HTML device profiles or content negotiation) may affect the content yielded by dereferencing a URI ๐Ÿงš.

If a resource is identified by more than one URI, the most specific should be used (e.g. http://www.w3.org/2000/06/interop-pressrelease.html.en instead of http://www.w3.org/2000/06/interop-pressrelease). (See the Reference Validation (section 3.2.1) for further information on reference processing.) ๐ŸŽ€

If the URI attribute is omitted altogether, the receiving application is expected to know the identity of the object. For example, a lightweight data protocol might omit this attribute given the identity of the object is part of the application context. This attribute may be omitted from at most one Reference in any particular SignedInfo, or Manifest ๐Ÿ“.

The optional Type attribute contains information about the type of object being signed. This is represented as a URI. For example:

Type="http://www.w3.org/2000/09/xmldsig#Object"
Type="http://www.w3.org/2000/09/xmldsig#Manifest"

The Type attribute applies to the item being pointed at, not its contents ๐Ÿ’…. For example, a reference that identifies an Object element containing a SignatureProperties element is still of type #Object. The type attribute is advisory. No validation of the type information is required by this specification ๐Ÿ™Œ.

4.3.3.2 The Reference Processing Model ๐Ÿ’–

okay so, first things first bestie: XPath is RECOMMENDED ๐ŸŽ€ but signature apps don't have to conform to the [XPath] spec to be conformant ๐Ÿ’… ๐ŸŒธ. The XPath data model, definitions (like node-sets) and syntax are used in this doc just to describe the functionality for anyone who wants to process XML-as-XML (instead of plain octets) as part of signature generation โœจ. If you want those features, a conformant [XPath] implementation is one way to do it, but it's NOT required ๐Ÿฆ‹. A sufficiently functional replacement for a node-set works too, as long as you only implement the XPath expression behaviors that this spec REQUIRED ๐Ÿงš. We're mostly gonna say "XPath" without repeating the caveat every time, so just know that "XPath nodesets" requirements can include a node-set functional equivalent, and XPath processing requirements can include app behaviors equivalent to the matching XPath behavior ๐Ÿซถ.

The data-type of the result of URI dereferencing or subsequent Transforms is either an octet stream or an XPath node-set ๐ŸŒˆ.

The Transforms in this doc are defined with respect to the input they need. Here's the default signature app behavior ๐Ÿ‘‘:

  • If the data object is an octet stream and the next transform requires a node-set, the signature application MUST attempt to parse the octets. ๐Ÿ’œ
  • If the data object is a node-set and the next transform requires octets, the signature application MUST attempt to convert the node-set to an octet stream using the REQUIRED canonicalization algorithm [XML-C14N]. ๐Ÿ”ฅ

Users can specify alternative transforms that override these defaults when transitioning between Transforms that expect different inputs โญ. The final octet stream contains the data octets being secured ๐ŸŒธ. The digest algorithm named by DigestMethod is then applied to those data octets, which gives you the DigestValue ๐Ÿ“.

Unless the URI-Reference is a 'same-document' reference as defined in [URI, Section 4.2], dereferencing the URI-Reference MUST result in an octet stream ๐Ÿ˜ญ. So an XML document identified by a URI is NOT parsed by the signature app unless the URI is a same-document reference, or a transform that needs XML parsing gets applied (see Transforms (section 4.3.3.1)) ๐Ÿ’…. When a fragment comes after an absolute or relative URI in the URI-Reference, the fragment's meaning is defined by the resource's MIME type ๐Ÿฆ‹. Even for XML docs, URI dereferencing (fragment processing included) might be done by a proxy for the signature app ๐Ÿ™ˆ. So reference validation might fail if fragment processing isn't done in a standard way (as defined in the next section for same-document references) ๐Ÿ’€. Which is why we RECOMMEND that the URI attribute NOT include fragment identifiers, and that this processing be specified as an additional XPath Transform โœจ๐ŸŽ€.

When a fragment is NOT preceded by a URI in the URI-Reference, XML signature apps MUST support the null URI and barename XPointer ๐Ÿ‘‘. We RECOMMEND supporting the same-document XPointers '#xpointer(/)' and '#xpointer(id("ID"))' if the app also plans to support Minimal Canonicalization or Canonical XML with Comments ๐Ÿฆ‹. (Otherwise URI="#foo" will automatically strip comments before Canonical XML with Comments can even be invoked ๐Ÿ˜ญ.) All other XPointer support is OPTIONAL ๐ŸŒˆ, especially barename and other XPointers in external resources, since the app may not control how the fragment gets generated (which leads to interop problems and validation failures) ๐Ÿ’€๐Ÿซถ.

Here are some examples of what the URI attribute identifies and how it gets dereferenced ๐Ÿงš:

URI="http://example.com/bar.xml"

Identifies the octets that represent the external resource 'http//example.com/bar.xml', which is probably an XML document given its file extension ๐ŸŽ€.

URI="http://example.com/bar.xml#chapter1"

Identifies the element with ID attribute value 'chapter1' of the external XML resource 'http://example.com/bar.xml', provided as an octet stream. Again, for interop's sake, the element identified as 'chapter1' SHOULD be obtained using an XPath transform rather than a URI fragment (barename XPointer resolution in external resources is NOT REQUIRED in this spec) ๐ŸŒธ.

URI=""

Identifies the nodeset (minus any comment nodes) of the XML resource containing the signature ๐Ÿ’œ.

URI="#chapter1"

Identifies a nodeset containing the element with ID attribute value 'chapter1' of the XML resource containing the signature. XML Signature (and its apps) modify this nodeset to include the element plus all descendants, including namespaces and attributes -- but not comments ๐Ÿ“โœจ.

4.3.3.3 Same-Document URI-References ๐ŸŒˆ

Dereferencing a same-document reference MUST result in an XPath node-set suitable for use by Canonical XML ๐Ÿ’–. Specifically, dereferencing a null URI (URI="") MUST result in an XPath node-set that includes every non-comment node of the XML document containing the URI attribute ๐Ÿ”ฅ. In a fragment URI, the characters after the number sign ('#') conform to the XPointer syntax [Xptr] ๐Ÿฆ‹. When processing an XPointer, the app MUST behave as if the root node of the XML document containing the URI attribute were used to initialize the XPointer evaluation context ๐Ÿ‘‘. The app MUST behave as if the result of XPointer processing were a node-set derived from the resultant location-set, as follows ๐Ÿงš:

  1. discard point nodes
  2. replace each range node with all XPath nodes having full or partial content within the range
  3. replace the root node with its children (if it is in the node-set)
  4. replace any element node E with E plus all descendants of E (text, comment, PI, element) and all namespace and attribute nodes of E and its descendant elements
  5. if the URI is not a full XPointer, then delete all comment nodes

The second-to-last replacement is necessary because XPointer typically indicates a subtree of an XML document's parse tree using just the element node at the root of the subtree ๐ŸŒธ. Canonical XML, on the other hand, treats a node-set as a set of nodes, where a missing descendant node means its representative text is missing from the canonical form ๐Ÿ˜ญ.

The last step is performed for null URIs, barename XPointers and child sequence XPointers ๐Ÿ’…. To keep comments while selecting an element by an identifier ID, use this full XPointer: URI='#xpointer(id("ID"))' โœจ. To keep comments while selecting the entire document, use this full XPointer: URI='#xpointer(/)' ๐ŸŽ€. This XPointer contains a simple XPath expression that includes the root node, which the second-to-last step above replaces with all nodes of the parse tree (all descendants, plus all attributes, plus all namespace nodes) ๐Ÿซถ.

4.3.3.4 The Transforms Element ๐Ÿฆ‹

The optional Transforms element contains an ordered list of Transform elements, which describe how the signer obtained the data object that was digested ๐Ÿ’œ. The output of each Transform is the input to the next one ๐ŸŒˆ. The input to the first Transform is the result of dereferencing the URI attribute of the Reference element ๐Ÿ“. The output from the last Transform is the input for the DigestMethod algorithm ๐Ÿ’–. When transforms are applied, the signer isn't signing the native (original) document, but the resulting (transformed) document ๐Ÿ˜ญ (see Only What is Signed is Secure (section 8.1)) ๐Ÿ’€.

Each Transform consists of an Algorithm attribute plus content parameters, if any, that fit the algorithm ๐Ÿงš. The Algorithm attribute value names the algorithm to be performed, and the Transform content gives extra data to control how the algorithm processes the transform input ๐ŸŽ€. (See Algorithm Identifiers and Implementation Requirements (section 6).)

As described in The Reference Processing Model (section 4.3.3.2), some transforms take an XPath node-set as input while others need an octet stream ๐Ÿ‘‘. If the actual input matches what the transform needs, the transform operates on the unaltered input โœจ. If the transform's input requirement differs from the format of the actual input, then the input has to be converted ๐ŸŒธ.

Some Transforms may need an explicit MIME type, charset (IANA registered "character set"), or other such info about the data they're receiving from an earlier Transform or the source data ๐Ÿ’…. No Transform algorithm specified in this doc needs that explicit info, though ๐Ÿฆ‹. Such data characteristics are provided as parameters to the Transform algorithm and should be described in the spec for that algorithm ๐Ÿซถ.

Examples of transforms include, but aren't limited to, base64 decoding [MIME], canonicalization [XML-C14N], XPath filtering [XPath], and XSLT [XSLT] ๐ŸŒˆ. The generic definition of the Transform element also allows application-specific transform algorithms ๐Ÿ“. For example, the transform could be a decompression routine given by a Java class appearing as a base64 encoded parameter to a Java Transform algorithm ๐Ÿ’œ. However, apps SHOULD refrain from using application-specific transforms if they want their signatures to be verifiable outside their application domain ๐Ÿ˜ญ๐Ÿ”ฅ. Transform Algorithms (section 6.6) defines the list of standard transformations ๐Ÿ’–.

Schema Definition:

<element name="Transforms">
  <complexType>
    <sequence>
      <element ref="ds:Transform" maxOccurs="unbounded"/>
    </sequence>
  </complexType>
</element>

  <element name="Transform">
    <complexType>
      <choice maxOccurs="unbounded">
        <any namespace="##other" processContents="lax" minOccurs="0"
         maxOccurs="unbounded"/>
        <element name="XSLT" type="string"/>
        <!-- should be an xsl:stylesheet element -->
        <element name="XPath" type="string"/>
      </choice>
      <attribute name="Algorithm" type="uriReference" use="required"/>
    </complexType>
  </element>

DTD:

<!ELEMENT Transforms (Transform+)>

<!ELEMENT Transform %Transform.ANY; >
<!ATTLIST Transform
          Algorithm    CDATA    #REQUIRED >

<!ELEMENT XPath (#PCDATA) >
<!ELEMENT XSLT (#PCDATA) >

4.3.3.5 The DigestMethod Element ๐Ÿ’…

okay bestie, DigestMethod is a required element ๐Ÿ”ฅ that names the digest algorithm you run on the signed object. It uses the general structure for algorithms from Algorithm Identifiers and Implementation Requirements (section 6.1) โœจ

If the result of the URI dereference and Transforms is an XPath node-set (or a sufficiently functional replacement the application implements), then it must be converted the way the Reference Processing Model (section 4.3.3.2) describes ๐Ÿซถ If the result is an octet stream instead, no conversion happens ๐Ÿ™ˆ (comments might still be there if Minimal Canonicalization or Canonical XML with Comments was specified in the Transforms). The digest algorithm then runs over the data octets of that resulting octet stream ๐Ÿฆ‹

Schema Definition:

<element name="DigestMethod">
  <complexType>
    <sequence>
      <any namespace="##any" processContents="lax" minOccurs="0"
      maxOccurs="unbounded"/>
    </sequence>
    <attribute name="Algorithm" type="uriReference" use="required"/>
  </complexType>
</element>
DTD:

<!ELEMENT DigestMethod %Method.ANY; >
<!ATTLIST DigestMethod
          Algorithm  CDATA   #REQUIRED >

4.3.3.6 The DigestValue Element ๐Ÿงš

DigestValue is the element that holds the encoded value of the digest ๐Ÿ’– The digest is always base64 encoded [MIME] ๐ŸŒธ

Schema Definition:

<element name="DigestValue" type="ds:CryptoBinary"/>
DTD:

<!ELEMENT DigestValue  (#PCDATA)  >
<!-- base64 encoded digest value -->

4.4 The KeyInfo Element ๐ŸŽ€

KeyInfo is an optional element that helps the recipient(s) get the key they need to validate the signature ๐Ÿ”‘ KeyInfo can hold keys, names, certificates, and other public key management info, like in-band key distribution or key agreement data ๐Ÿ’œ This spec only defines a few simple types, but applications can put their own key identification and exchange stuff in here through the XML-namespace facility [XML-ns] โœจ

If KeyInfo is omitted, the recipient is expected to figure out the key from application context information ๐Ÿคท Multiple declarations inside KeyInfo refer to the same key ๐Ÿ’… Applications can use any mechanism they want by including elements from a different namespace ๐ŸŒˆ but compliant versions MUST implement KeyValue (section 4.4.2) and SHOULD implement RetrievalMethod (section 4.4.3) ๐Ÿซถ

Here's the list of KeyInfo types this spec defines. You can use these inside the RetrievalMethod Type attribute to describe the remote KeyInfo structure, represented as an octet stream ๐Ÿ‘‘

Besides the types above (which have structures we define), we also specify one more type for a binary X.509 Certificate ๐Ÿ’–

Schema Definition:

<element name="KeyInfo">
  <complexType>
    <choice maxOccurs="unbounded">
      <any processContents="lax" namespace="##other" minOccurs="0"
       maxOccurs="unbounded"/>
      <element name="KeyName" type="string"/>
      <element ref="ds:KeyValue"/>
      <element ref="ds:RetrievalMethod"/>
      <element ref="ds:X509Data"/>
      <element ref="ds:PGPData"/>
      <element ref="ds:SPKIData"/>
      <element name="MgmtData" type="string"/>
    </choice>
    <attribute name="Id" type="ID" use="optional"/>
  </complexType>
</element>
DTD:

<!ELEMENT KeyInfo %Key.ANY; >
<!ATTLIST KeyInfo
          Id ID  #IMPLIED >

4.4.1 The KeyName Element ๐Ÿ“

KeyName holds a string value the signer can use to tell the recipient which key to use ๐Ÿ—๏ธ Usually KeyName has an identifier tied to the key pair that signed the message, but it can also hold other protocol info that points to a key pair indirectly โœจ (Common uses are simple string names for keys, a key index, a distinguished name (DN), an email address, and so on ๐Ÿ’…)

Schema Definition:

<!-- type declared in KeyInfo -->
DTD:

<!ELEMENT KeyName (#PCDATA) >

4.4.2 The KeyValue Element ๐Ÿฆ‹

KeyValue holds a single public key that could be useful for validating the signature ๐Ÿ’– Structured formats for DSA (REQUIRED) and RSA (RECOMMENDED) public keys are defined in Signature Algorithms (section 6.4) ๐Ÿ”ฅ

Schema Definition:

<element name="KeyValue">
  <complexType mixed="true">
    <choice>
      <any namespace="##other" processContents="lax" minOccurs="0"
       maxOccurs="unbounded"/>
      <element ref="ds:DSAKeyValue"/>
      <element ref="ds:RSAKeyValue"/>
    </choice>
  </complexType>
</element>

DTD:
<!ELEMENT KeyValue    %Key.ANY; >

4.4.3 The RetrievalMethod Element ๐Ÿงšโ€โ™€๏ธ

A RetrievalMethod element inside KeyInfo points to KeyInfo information stored somewhere else ๐Ÿ—บ๏ธ For example, several signatures in one document might all use a key verified by an X.509v3 certificate chain that shows up once in the document or lives remotely outside it ๐Ÿ˜ญ Each signature's KeyInfo can reference that chain with one RetrievalMethod element, instead of copying the whole chain in as a sequence of X509Certificate elements ๐Ÿซถ

RetrievalMethod uses the same syntax and dereferencing behavior as Reference's URI (section 4.3.3.1) and The Reference Processing Model (section 4.3.3.2), except there's no DigestMethod or DigestValue child elements and the URI is mandatory ๐Ÿ’… Note: if dereferencing and transforming the specified URI gives you a node set, it may need to be canonicalized. All the KeyInfo types this spec defines (section 4.4) represent octets, so the Signature application is expected to try canonicalizing the node set via The Reference Processing Model (section 4.3.3.2) ๐ŸŒˆ

Type is an optional identifier for the type of data to be retrieved โœจ

Schema Definition

<element name="RetrievalMethod">
  <complexType>
    <sequence>
      <element ref="ds:Transforms" minOccurs="0"/>
    </sequence>
    <attribute name="URI" type="uriReference"/>
    <attribute name="Type" type="uriReference" use="optional"/>
  </complexType>
</element>
DTD

<!ELEMENT RetrievalMethod (Transforms?) >
<!ATTLIST RetrievalMethod
          URI       CDATA   #REQUIRED
          Type      CDATA   #IMPLIED >

4.4.4 The X509Data Element ๐Ÿ‘‘

Identifier
      Type="http://www.w3.org/2000/09/xmldsig#X509Data"
      (this can be used within a RetrievalMethod or Reference element
      to identify the referent's type)

An X509Data element inside KeyInfo holds one or more identifiers of keys or X509 certificates (or certificate identifiers or revocation lists) ๐ŸŽ€ Five types of X509Data are defined ๐ŸŒธ

  1. The X509IssuerSerial element, which contains an X.509 issuer distinguished name/serial number pair that SHOULD be compliant with RFC2253 [LDAP-DN] ๐Ÿงพ
  2. The X509SubjectName element, which contains an X.509 subject distinguished name that SHOULD be compliant with RFC2253 [LDAP-DN] ๐Ÿซถ
  3. The X509SKI element, which contains an X.509 subject key identifier value. ๐Ÿ”‘
  4. The X509Certificate element, which contains a base64-encoded [X509v3] certificate, and ๐Ÿ“œ
  5. The X509CRL element, which contains a base64-encoded certificate revocation list (CRL) [X509v3]. ๐Ÿšซ

Multiple declarations about a single certificate (like an X509SubjectName and an X509IssuerSerial element) MUST be grouped inside a single X509Data element ๐Ÿ’… Multiple declarations about the same key but different certificates (related to that one key) MUST be grouped within a single KeyInfo element, but MAY occur in multiple X509Data elements ๐Ÿฆ‹ For example, this block has two pointers to certificate-A (issuer/serial number and SKI), a single reference to certificate-B (SubjectName), and also shows certificate elements in use ๐Ÿ˜ญ

<KeyInfo>
  <X509Data> <!-- two pointers to certificate-A -->
    <X509IssuerSerial>
      <X509IssuerName>CN=TAMURA Kent, OU=TRL, O=IBM,
        L=Yamato-shi, ST=Kanagawa, C=JP</X509IssuerName>
      <X509SerialNumber>12345678</X509SerialNumber>
    </X509IssuerSerial>
    <X509SKI>31d97bd7</X509SKI>
  </X509Data>
  <X509Data> <!-- single pointer to certificate-B -->
    <X509SubjectName>Subject of Certificate B</X509SubjectName>
  </X509Data> <!-- certificate chain -->
    <!--Signer cert, issuer CN=arbolCA,OU=FVT,O=IBM,C=US, serial 4-->
    <X509Certificate>MIICXTCCA..</X509Certificate>
    <!-- Intermediate cert subject CN=arbolCA,OU=FVTO=IBM,C=US
         issuer,CN=tootiseCA,OU=FVT,O=Bridgepoint,C=US -->
    <X509Certificate>MIICPzCCA...</X509Certificate>
    <!-- Root cert subject CN=tootiseCA,OU=FVT,O=Bridgepoint,C=US -->
    <X509Certificate>MIICSTCCA...</X509Certificate>
  </X509Data>
</KeyInfo>

Heads up ๐Ÿ™ˆ there's no direct provision for a PKCS#7 encoded "bag" of certificates or CRLs. That said, a set of certificates or a CRL can sit inside an X509Data element, and multiple X509Data elements can show up in one KeyInfo โœจ Whenever multiple certificates appear in one X509Data element, at least one of them must contain the public key that verifies the signature ๐Ÿ”ฅ

Schema Definition

<element name="X509Data">
  <complexType>
    <choice>
      <sequence maxOccurs="unbounded">
        <choice>
          <element ref="ds:X509IssuerSerial"/>
          <element name="X509SKI" type="ds:CryptoBinary"/>
          <element name="X509SubjectName" type="string"/>
          <element name="X509Certificate" type="ds:CryptoBinary"/>
        </choice>
      </sequence>
      <element name="X509CRL" type="ds:CryptoBinary"/>
    </choice>
  </complexType>
</element>

<element name="X509IssuerSerial">
  <complexType>
    <sequence>
      <element name="X509IssuerName" type="string"/>
      <element name="X509SerialNumber" type="integer"/>
    </sequence>
  </complexType>
</element>

DTD

<!ELEMENT X509Data ((X509IssuerSerial | X509SKI | X509SubjectName |
                     X509Certificate)+ | X509CRL)>
<!ELEMENT X509IssuerSerial (X509IssuerName, X509SerialNumber) >
<!ELEMENT X509IssuerName (#PCDATA) >
<!ELEMENT X509SubjectName (#PCDATA) >
<!ELEMENT X509SerialNumber (#PCDATA) >
<!ELEMENT X509SKI (#PCDATA) >
<!ELEMENT X509Certificate (#PCDATA) >
<!ELEMENT X509CRL (#PCDATA) >

4.4.5 The PGPData element ๐Ÿ”

Identifier: Type="http://www.w3.org/2000/09/xmldsig#PGPData" (this can be used within a RetrievalMethod or Reference element to identify the referent's type ๐ŸŽ€)

okay so PGPData is the KeyInfo element for PGP public key pairs and the signatures on those keys ๐Ÿ”‘โœจ The PGPKeyID holds a string that's a standard PGP public key identifier, defined in [PGP, section 11.2] ๐Ÿ’– The PGPKeyPacket holds a base64-encoded Key Material Packet, defined in [PGP, section 5.5] ๐Ÿงš And the OpenPGP working group is allowed to define other sub-types of PGPData later, so keep an eye out ๐Ÿ‘€

Schema Definition:

<element name="PGPData">
  <complexType>
    <choice>

      <any namespace="##other" processContents="lax" minOccurs="0"
      maxOccurs="unbounded"/>
      <sequence>
        <element name="PGPKeyID" type="string"/>
        <element name="PGPKeyPacket" type="ds:CryptoBinary"/>
      </sequence>
    </choice>
  </complexType>
</element>

DTD:

<!ELEMENT PGPData (PGPKeyID, PGPKeyPacket)  >
<!ELEMENT PGPKeyPacket  (#PCDATA)  >
<!ELEMENT PGPKeyID  (#PCDATA)  >

4.4.6 The SPKIData element ๐ŸŒธ

Identifier: Type="http://www.w3.org/2000/09/xmldsig#SPKIData" (this can be used within a RetrievalMethod or Reference element to identify the referent's type ๐Ÿฆ‹)

so SPKIData is the one for SPKI public key pairs, certificates, and other SPKI data ๐Ÿ’œ Its content is expected to be a Canonical S-expression, bestie ๐Ÿ“

Schema Definition:

<element name="SPKIData" type="string"/>

DTD:

<!ELEMENT SPKIData (#PCDATA) >

4.4.7 The MgmtData element ๐ŸŒˆ

Identifier: Type="http://www.w3.org/2000/09/xmldsig#MgmtData" (this can be used within a RetrievalMethod or Reference element to identify the referent's type โญ)

MgmtData is giving in-band key distribution or agreement data ๐Ÿค It's a string value, and the examples are DH key exchange, RSA key encryption, etc. ๐Ÿ’…

Schema Definition:

<!-- type declared in KeyInfo -->

DTD:

<!ELEMENT MgmtData (#PCDATA)>

4.5 The Object Element โœจ

Identifier: Type="http://www.w3.org/2000/09/xmldsig#Object" (this can be used within a Reference element to identify the referent's type ๐ŸŽ€)

Object is an optional element that can show up one or more times ๐Ÿซถ When it's there, it can hold any data at all ๐ŸŒธ It can also carry optional MIME type, ID, and encoding attributes, which is very main character energy ๐Ÿ‘‘

The MimeType attribute is optional and describes the data inside the Object ๐Ÿ’– It's a string whose values are defined by [MIME]. For example, if the Object holds XML, the MimeType could be text/xml. This attribute is purely advisory, and this specification doesn't require any validation of the MimeType information ๐Ÿ™ˆ

The Object's Id is commonly referenced from a Reference in SignedInfo, or Manifest ๐Ÿ”ฅ This element is typically used for enveloping signatures, where the object being signed goes right inside the signature element ๐Ÿงš The digest is calculated over the entire Object element, start and end tags included ๐Ÿ’…

The Object's Encoding attribute can be used to give a URI that identifies how the object is encoded, like a binary file ๐Ÿฆ‹

Note, if the application wants the <Object> tags left out of the digest calculation, the Reference has to identify the actual data object (easy for XML documents), or a transform has to be used to strip the Object tags (likely where the data object is non-XML) โญ Leaving out the object tags might be wanted when you want the signature to stay valid even if the data object gets moved from inside a signature to outside it (or the other way around) ๐ŸŒˆ It might also be wanted when the content of the Object is an encoding of an original binary document, and you want to extract and decode it so you sign the original bitwise representation ๐Ÿ’œ

Schema Definition:

<element name="Object">
  <complexType mixed="true">
    <sequence maxOccurs="unbounded">
      <any namespace="##any" processContents="lax"/>

    </sequence>
    <attribute name="Id" type="ID" use="optional"/>
    <attribute name="MimeType" type="string" use="optional"/>
       <!-- add a grep facet -->
    <attribute name="Encoding" type="uriReference" use="optional"/>
  </complexType>
</element>

DTD:

<!ELEMENT Object %Object.ANY; >
<!ATTLIST Object
          Id ID  #IMPLIED
          MimeType   CDATA   #IMPLIED
          Encoding   CDATA   #IMPLIED >

5.0 Additional Signature Syntax ๐ŸŽ€

This section covers the optional-to-implement Manifest and SignatureProperties elements, and it explains how XML processing instructions and comments get handled ๐Ÿซถ For Manifest and SignatureProperties, this section defines the syntax and barely any behaviour, since that's left up to the application ๐Ÿ’… These elements can appear anywhere the parent's content model allows, but the Signature content model only lets them show up within Object ๐Ÿ”ฅ

5.1 The Manifest Element ๐Ÿ“œ

Identifier: Type="http://www.w3.org/2000/09/xmldsig#Manifest" (this can be used within a Reference element to identify the referent's type ๐Ÿ’–)

The Manifest element is a list of References ๐Ÿงš The difference from the list in SignedInfo is that the application decides which digests, if any, actually get checked against the referenced objects, and what to do if an object can't be reached or the digest compare fails ๐Ÿ™ˆ If a Manifest is pointed to from SignedInfo, the digest over the Manifest itself gets checked by the core signature validation behaviour ๐Ÿ” The digests inside that Manifest get checked at the application's discretion โœจ And if a Manifest is referenced from another Manifest, even the overall digest of that two-level-deep Manifest might not get checked ๐Ÿ˜ญ

Schema Definition:

<element name="Manifest">
  <complexType>
    <sequence>
      <element ref="ds:Reference" maxOccurs="unbounded"/>

    </sequence>
    <attribute name="Id" type="ID" use="optional"/>
  </complexType>
</element>

DTD:

<!ELEMENT Manifest (Reference+)  >
<!ATTLIST Manifest
          Id ID  #IMPLIED >

5.2 The SignatureProperties Element ๐Ÿฆ‹

Identifier: Type="http://www.w3.org/2000/09/xmldsig#SignatureProperties" (this can be used within a Reference element to identify the referent's type ๐ŸŒธ)

Extra info about how the signature(s) got made can go in a SignatureProperty element ๐Ÿ•ฐ๏ธ Think date/time stamps, or the serial number of the cryptographic hardware used to make the signature ๐Ÿ’…

Schema Definition:

<element name="SignatureProperties">
  <complexType>
    <sequence>
   <element ref="ds:SignatureProperty" maxOccurs="unbounded"/>
  </sequence>
    <attribute name="Id" type="ID" use="optional"/>
  </complexType>
</element>

   <element name="SignatureProperty">
     <complexType mixed="true">
       <choice minOccurs="0" maxOccurs="unbounded">
         <any namespace="##other" processContents="lax" minOccurs="0"
         maxOccurs="unbounded"/>
       </choice>
       <attribute name="Target" type="uriReference" use="required"/>
       <attribute name="Id" type="ID" use="optional"/>
       </complexType>
   </element>

DTD:

<!ELEMENT SignatureProperties (SignatureProperty+)  >
<!ATTLIST SignatureProperties
          Id ID   #IMPLIED  >

<!ELEMENT SignatureProperty %SignatureProperty.ANY >
<!ATTLIST SignatureProperty
          Target CDATA    #REQUIRED
          Id ID  #IMPLIED  >

5.3 Processing Instructions in Signature Elements ๐Ÿงš

No XML processing instructions (PIs) are used by this specification ๐Ÿ™…โ€โ™€๏ธ

Heads up, though: PIs placed inside SignedInfo by an application will be signed, unless the CanonicalizationMethod algorithm throws them away ๐Ÿ” (This is true for any signed XML content.) All of the CanonicalizationMethods specified within this specification keep PIs ๐Ÿ’– When a PI is part of content that gets signed (like within SignedInfo or in referenced XML documents), any change to the PI will obviously cause a signature failure ๐Ÿ˜ญ

5.4 Comments in Signature Elements ๐Ÿ’ฌ

XML comments are not used by this specification ๐Ÿ™…โ€โ™€๏ธ

Note that unless CanonicalizationMethod removes comments within SignedInfo or any other referenced XML (which [XML-C14N] does), they will be signed ๐Ÿซฃ So if they're kept, changing a comment will cause a signature failure ๐Ÿ’€ Similarly, the XML signature over any XML data will be sensitive to comment changes, unless a comment-ignoring canonicalization/transform method, such as the Canonical XML [XML-C14N], is specified ๐ŸŽ€

6.0 Algorithms ๐Ÿงฎ

This section identifies the algorithms used with the XML digital signature specification ๐Ÿฆ‹ Each entry has the identifier to use in Signature elements, a reference to the formal specification, and definitions (where they apply) for how keys and the results of cryptographic operations are represented ๐Ÿ’œ

6.1 Algorithm Identifiers and Implementation Requirements ๐Ÿ‘‘

Algorithms are identified by URIs that show up as an attribute on the element that names the algorithm's role (DigestMethod, Transform, SignatureMethod, or CanonicalizationMethod) ๐ŸŒˆ All the algorithms here take parameters, but in lots of cases the parameters are implicit ๐Ÿ™ˆ For example, a SignatureMethod is implicitly given two parameters: the keying info and the output of CanonicalizationMethod ๐Ÿ” Explicit extra parameters to an algorithm show up as content elements inside the algorithm role element ๐Ÿ’… Those parameter elements have a descriptive element name, which is often algorithm specific, and they MUST be in the XML Signature namespace or an algorithm specific namespace ๐Ÿซถ

This specification defines a set of algorithms, their URIs, and the requirements for implementing them ๐Ÿ“‹ The requirements are about implementation, not about what's needed for signature use ๐Ÿง  And the mechanism is extensible, so signature applications can use alternative algorithms too ๐ŸŒธ

(Note that the normative identifier is the complete URI in the table, even though they're sometimes abbreviated in XML syntax, e.g., "&dsig;base64".) โœจ

Algorithm Type
   Algorithm - Requirements - Algorithm URI
Digest
   SHA1  - REQUIRED - &dsig;sha1
Encoding
   base64  - REQUIRED - &dsig;base64
MAC
   HMAC-SHA1 - REQUIRED - &dsig;hmac-sha1
Signature
   DSAwithSHA1(DSS) - REQUIRED - &dsig;dsa-sha1
   RSAwithSHA1 - RECOMMENDED - &dsig;rsa-sha1
Canonicalization
   minimal - RECOMMENDED - &dsig;minimal
   Canonical XML with Comments - RECOMMENDED -
      http://www.w3.org/TR/2000/CR-xml-c14n-20001026#WithComments
   Canonical XML (omits comments) - REQUIRED -
      http://www.w3.org/TR/2000/CR-xml-c14n-20001026
Transform
   XSLT - OPTIONAL - http://www.w3.org/TR/1999/REC-xslt-19991116
   XPath - RECOMMENDED -
      http://www.w3.org/TR/1999/REC-xpath-19991116
   Enveloped Signature* - REQUIRED - &dsig;enveloped-signature

* The Enveloped Signature transform removes the Signature element from the calculation of the signature when the signature sits inside the content it's signing ๐Ÿซง This MAY be implemented via the RECOMMENDED XPath specification specified in 6.6.4: Enveloped Signature Transform, but it MUST have the same effect as the one specified by the XPath Transform ๐Ÿ’–

6.2. Message Digests

okay so only one digest algorithm is defined in this doc ๐Ÿ’… but the US Advanced Encryption Standard crowd is expected to cook up more strong ones, so stay tuned โœจ and ngl, using MD5 [MD5] is NOT RECOMMENDED bc recent advances in cryptography have made people side-eye its strength ๐Ÿ˜ญ

6.2.1. SHA-1

Identifier:

http://www.w3.org/2000/09/xmldsig#sha1

The SHA-1 algorithm [SHA-1] takes no explicit parameters, so it's giving low-maintenance ๐Ÿงš Here's an example of a SHA-1 DigestAlg element: <DigestMethod Algorithm="&dsig;sha1"/>

A SHA-1 digest is a 160-bit string. The content of the DigestValue element shall be the base64 encoding of that bit string, viewed as a 20-octet octet stream ๐ŸŒธ For example, take this message digest from Appendix A of the SHA-1 standard:

A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D

and the DigestValue element for it would be:

<DigestValue>qZk+NkcGgWq6PiVxeFDCbJzQ2J0=</DigestValue>

6.3. Message Authentication Codes

MAC algorithms take two implicit parameters: their keying material, which is determined from KeyInfo, and the octet stream output by CanonicalizationMethod ๐Ÿ” MACs and signature algorithms are syntactically identical, but a MAC implies a shared secret key, while a signature implies something else entirely ๐Ÿซถ

6.3.1. HMAC

Identifier:

http://www.w3.org/2000/09/xmldsig#hmac-sha1

The HMAC algorithm (RFC2104 [HMAC]) takes the truncation length in bits as a parameter. If that parameter isn't specified, then all the bits of the hash get output ๐Ÿ“ Here's an example of an HMAC SignatureMethod element:

<SignatureMethod Algorithm="&dsig;hmac-sha1">
   <HMACOutputLength>128</HMACOutputLength>
</SignatureMethod>

The output of the HMAC algorithm is ultimately the output (possibly truncated) of the chosen digest algorithm. This value shall be base64 encoded in the same straightforward fashion as the output of the digest algorithms ๐Ÿฆ‹ For example, the SignatureValue element for the HMAC-SHA1 digest

9294727A 3638BB1C 13F48EF8 158BFC9D

from the test vectors in [HMAC] would be:

<SignatureValue>kpRyejY4uxwT9I74FYv8nQ==</SignatureValue>

Schema Definition:

<element name="HMACOutputLength" type="integer"/>

DTD:

<!ELEMENT HMACOutputLength (#PCDATA)>

6.4. Signature Algorithms

Signature algorithms take two implicit parameters too: their keying material, determined from KeyInfo, and the octet stream output by CanonicalizationMethod ๐Ÿ’œ Signature and MAC algorithms are syntactically identical, but a signature implies public key cryptography, which is the whole main character energy of this section ๐Ÿ‘‘

6.4.1. DSA

Identifier:

http://www.w3.org/2000/09/xmldsig#dsa-sha1

The DSA algorithm [DSS] takes no explicit parameters. Here's an example of a DSA SignatureMethod element:

<SignatureMethod Algorithm="&dsig;dsa"/>

The output of the DSA algorithm is a pair of integers, usually referred to as the pair (r, s). The signature value is the base64 encoding of the concatenation of two octet streams, which come from octet-encoding the values r and s respectively ๐ŸŽ€ Integer to octet stream conversion has to be done according to the I2OSP operation defined in the RFC 2437 [PKCS1] specification, with a k parameter equal to 20. For example, here's the SignatureValue element for a DSA signature (r, s), with the values written in hexadecimal:

r = 8BAC1AB6 6410435C B7181F95 B16AB97C 92B341C0
s = 41E2345F 1F56DF24 58F426D1 55B4BA2D B6DCD8C8

from the example in Appendix 5 of the DSS standard would be:

<SignatureValue>
i6watmQQQ1y3GB+VsWq5fJKzQcBB4jRfH1bfJFj0JtFVtLotttzYyA==</SignatureValue>

DSA key values have the following set of fields ๐ŸŒˆ P, Q, G and Y are mandatory when they appear as a key value. J, seed and pgenCounter are optional but should be present. (The seed and pgenCounter fields must appear together or be absent.) All parameters are encoded as base64 [MIME] values.

Schema:

<element name="DSAKeyValue">
  <complexType>
    <sequence>
      <sequence>
        <element name="P" type="ds:CryptoBinary"/>
        <element name="Q" type="ds:CryptoBinary"/>
        <element name="G" type="ds:CryptoBinary"/>
        <element name="Y" type="ds:CryptoBinary"/>
        <element name="J" type="ds:CryptoBinary" minOccurs="0"/>
      </sequence>
      <sequence minOccurs="0">
        <element name="Seed" type="ds:CryptoBinary"/>
        <element name="PgenCounter" type="ds:CryptoBinary"/>
      </sequence>
    </sequence>
  </complexType>
</element>

DTD:

<!ELEMENT DSAKeyValue (P, Q, G, Y, J?, (Seed, PgenCounter)?) >
<!ELEMENT P (#PCDATA) >
<!ELEMENT Q (#PCDATA) >
<!ELEMENT G (#PCDATA) >
<!ELEMENT Y (#PCDATA) >
<!ELEMENT J (#PCDATA) >
<!ELEMENT Seed (#PCDATA) >
<!ELEMENT PgenCounter (#PCDATA) >

6.4.2. PKCS1

Identifier:

http://www.w3.org/2000/09/xmldsig#rsa-sha1

Arbitrary-length integers (aka "bignums", like RSA modulii) are represented in XML as octet strings ๐Ÿง  First the integer value gets converted to a "big endian" bitstring. Then the bitstring is padded with leading zero bits so the total number of bits == 0 mod 8, which means an even number of bytes. If the bitstring has entire leading bytes that are zero, those get removed, so the high-order byte is always non-zero. Then this octet string is base64 [MIME] encoded. (The integer-to-octet-string conversion is equivalent to IEEE 1363's I2OSP [1363] with minimal length.)

The expression "RSA algorithm" as used in this document refers to the RSASSA-PKCS1-v1_5 algorithm described in RFC 2437 [PKCS1]. The RSA algorithm takes no explicit parameters. An example of an RSA SignatureMethod element is:

<SignatureMethod Algorithm="&dsig;rsa-
sha1"/>

The SignatureValue content for an RSA signature is the base64 [MIME] encoding of the octet string computed as per RFC 2437 [PKCS1, section 8.1.1: Signature generation for the RSASSA-PKCS1-v1_5 signature scheme]. As specified in the EMSA-PKCS1-V1_5-ENCODE function RFC 2437 [PKCS1, section 9.2.1], the value input to the signature function MUST contain a pre-pended algorithm object identifier for the hash function. However, the availability of an ASN.1 parser and recognition of OIDs is not required of a signature verifier ๐Ÿ™ˆ The PKCS#1 v1.5 representation looks like this:

CRYPT (PAD (ASN.1 (OID, DIGEST (data))))

Note that the padded ASN.1 will be of the following form:

01 | FF* | 00 | prefix | hash

where "|" is concatentation, "01", "FF", and "00" are fixed octets of the corresponding hexadecimal value, "hash" is the SHA1 digest of the data, and "prefix" is the ASN.1 BER SHA1 algorithm designator prefix required in PKCS1 [RFC 2437], that is:

hex 30 21 30 09 06 05 2B 0E 03 02 1A 05 00 04 14

This prefix is included to make it easier to use standard cryptographic libraries ๐Ÿ“š The FF octet MUST be repeated the maximum number of times such that the value of the quantity being CRYPTed is one octet shorter than the RSA modulus.

The resulting base64 [MIME] string is the value of the child text node of the SignatureValue element, for example:

<SignatureValue>IWijxQjUrcXBYoCei4QxjWo9Kg8D3p9tlWoT4
t0/gyTE96639In0FZFY2/rvP+/bMJ01EArmKZsR5VW3rwoPxw=
</SignatureValue>

RSA key values have two fields, Modulus and Exponent:

<RSAKeyValue>

<Modulus>xA7SEU+e0yQH5rm9kbCDN9o3aPIo7HbP7tX6WOocLZAtNfyxSZDU16ksL6W

jubafOqNEpcwR3RdFsT7bCqnXPBe5ELh5u4VEy19MzxkXRgrMvavzyBpVRgBUwUlV
      5foK5hhmbktQhyNdy/6LpQRhDUDsTvK+g9Ucj47es9AQJ3U=
      </Modulus>
      <Exponent>AQAB</Exponent>
   </RSAKeyValue>

Schema:

<element name="RSAKeyValue">
  <complexType>
    <sequence>
      <element name="Modulus" type="ds:CryptoBinary"/>
      <element name="Exponent" type="ds:CryptoBinary"/>
    </sequence>
  </complexType>
</element>

DTD:

<!ELEMENT RSAKeyValue (Modulus, Exponent) >
<!ELEMENT Modulus (#PCDATA) >
<!ELEMENT Exponent (#PCDATA) >

6.5. Canonicalization Algorithms

If canonicalization is performed over octets, the canonicalization algorithms take two implicit parameters: the content and its charset ๐Ÿฐ The charset is derived according to the rules of the transport protocols and media types (for example, RFC2376 [XML-MT] defines the media types for XML). This information is necessary to correctly sign and verify documents, and it often requires careful server-side configuration, so don't skip it ๐Ÿ˜ค

Various canonicalization algorithms require conversion to [UTF-8]. The two algorithms below understand at least [UTF-8] and [UTF-16] as input encodings. We RECOMMEND that externally specified algorithms do the same. Knowledge of other encodings is OPTIONAL.

Various canonicalization algorithms transcode from a non-Unicode encoding to Unicode. The two algorithms below perform text normalization during transcoding [NFC]. We RECOMMEND that externally specified canonicalization algorithms do the same. (Note, there can be ambiguities when converting existing charsets to Unicode. For an example, see the XML Japanese Profile [XML-Japanese] NOTE ๐Ÿ™ƒ)

6.5.1. Minimal Canonicalization

Identifier:

http://www.w3.org/2000/09/xmldsig#minimal

An example of a minimal canonicalization element is:

<CanonicalizationMethod Algorithm="&dsig;minimal"/>

The minimal canonicalization algorithm:

  • converts the character encoding to UTF-8 (without any byte order mark (BOM)). If an encoding is given in the XML declaration, it must be removed. Implementations MUST understand at least [UTF-8] and [UTF-16] as input encodings. Non-Unicode to Unicode transcoding MUST perform text normalization [NFC].
  • normalizes line endings as provided by [XML]. (See XML and Canonicalization and Syntactical Considerations (section 7).)

This algorithm requires as input the octet stream of the resource to be processed, and the algorithm outputs an octet stream ๐Ÿ’– When used to canonicalize SignedInfo, the algorithm MUST be provided with the octets that represent the well-formed SignedInfo element (and its children and content), as described in The CanonicalizationMethod Element (section 4.3.1).

If the signature application has a node set, then the signature application must convert it into octets as described in The Reference Processing Model (section 4.3.3.2). However, Minimal Canonicalization is NOT RECOMMENDED for processing XPath node-sets, the results of same-document URI references, and the output of other types of XML-based transforms. It is only RECOMMENDED for simple character normalization of well-formed XML that has no namespace or external entity complications โญ

6.5.2. Canonical XML

Identifier for REQUIRED Canonical XML (omits comments):

http://www.w3.org/TR/2000/CR-xml-c14n-20001026

Identifier for Canonical XML with Comments:

http://www.w3.org/TR/2000/CR-xml-c14n-20001026#WithComments

An example of an XML canonicalization element is:

<CanonicalizationMethod Algorithm="http://www.w3.org/TR/2000/CR-xml-
c14n-20001026"/>

The normative specification of Canonical XML is [XML-C14N]. The algorithm can take as input either an octet stream or an XPath node-set (or a sufficiently functional alternative), and it produces an octet stream as output ๐Ÿฆ‹ Canonical XML is easily parameterized (via an additional URI) to omit or retain comments, which is so iconic ๐Ÿ‘‘

6.6 Transform Algorithms

okay so a Transform algorithm only has one implicit parameter ๐Ÿ’– It's an octet stream, and it comes either from the Reference or from the output of an earlier Transform.

Application developers are strongly encouraged to support every transform in this section as RECOMMENDED ๐Ÿซถ unless their environment is resource-constrained enough that it's genuinely impractical. Supporting them all maximizes interoperability, and libraries should exist that let you add these without a ton of dev work โœจ

6.6.1 Canonicalization

Any canonicalization algorithm that can be used for CanonicalizationMethod (like the ones in Canonicalization Algorithms (section 6.5)) can also be used as a Transform ๐Ÿฆ‹

6.6.2 Base64

Identifiers: http://www.w3.org/2000/09/xmldsig#base64

The normative spec for base 64 decoding transforms is [MIME] ๐ŸŒธ The base64 Transform element has no content, and the algorithms do the decoding for you. This one is useful when an app wants to sign the raw data inside an element's encoded content ๐Ÿ’…

This transform needs an octet stream as input. If you hand it an XPath node-set (or something equally capable), it gets turned into an octet stream by doing the logical equivalent of two steps: first applying an XPath transform with the expression self::text(), then taking the string-value of the node-set ๐Ÿงš So if an element is found with a barename XPointer in the Reference URI, and its content is only base64 character data, this transform quietly strips off the start and end tags of that element, plus any descendant elements, descendant comments, and processing instructions. The output is an octet stream ๐ŸŽ€

6.6.3 XPath Filtering

Identifier: http://www.w3.org/TR/1999/REC-xpath-19991116

The normative spec for XPath expression evaluation is [XPath] ๐Ÿ’œ The XPath expression being evaluated shows up as the character content of a transform parameter child element named XPath.

The input for this transform is an XPath node-set ๐Ÿ”ฅ Heads up: if the actual input is an XPath node-set coming from a null URI or a barename XPointer dereference, then comment nodes have already been dropped. If the actual input is an octet stream instead, the application MUST convert that octet stream into an XPath node-set that works with Canonical XML with Comments. (The REQUIRED Canonical XML algorithm that runs later will strip those comments back out.) In other words, the input node-set should end up matching the one you'd get from this process:

  1. Start an XPath evaluation context with the initial node set to the input XML document's root node, and set the context position and size to 1.
  2. Evaluate the XPath expression (//. | //@* | //namespace::*)

Evaluating that expression pulls in every node in the document, comments included, to build the node-set that represents the octet stream ๐Ÿ‘‘

The output of this transform is also an XPath node-set ๐ŸŒˆ The XPath expression in the XPath parameter gets evaluated once for each node in the input node-set. The result is converted to a boolean. If that boolean is true, the node goes into the output node-set. If it's false, the node gets left out.

Note: Even when comments have been removed from the input node-set, the comment nodes still live in the underlying parse tree, and they can split text nodes apart. For example, the markup <e>Hello, <!-- comment --> world!</e> has two text nodes, so self::text()[string()="Hello, world!"] would fail ๐Ÿ˜ญ If you run into this, you can either canonicalize the document before the XPath transform to physically remove the comments, or match the node based on the parent element's string value, like self::text()[string(parent::e)="Hello, world!"].

The whole point of this transform is to make sure that only specifically defined changes to the input XML document are allowed after the signature is attached ๐Ÿ”’ It works by leaving out exactly the nodes that are allowed to change once the signature exists, and including every other input node in the output. The XPath expression's author is responsible for including all nodes whose change could affect how the transform output gets interpreted in the application context ๐Ÿง

Here's an important scenario: a document that needs two enveloped signatures. Each signature has to leave itself out of its own digest calculations. But it's also necessary to exclude the second signature element from the first signature's digest calculation, so that adding the second signature doesn't break the first one ๐Ÿ’…

For each node of the input node-set, the XPath transform sets up this evaluation context:

  • A context node equal to a node of the input node-set.
  • A context position, initialized to 1.
  • A context size, initialized to 1.
  • A library of functions equal to the function set defined in XPath, plus a function named here.
  • A set of variable bindings. No means for initializing these is defined, so the set of variable bindings is empty, and using a variable reference in the XPath expression results in an error.
  • The set of namespace declarations in scope for the XPath expression.

Because of how the context node is set, the XPath expressions in this transform end up looking a lot like the ones used in [XSLT], except that size and position are always 1. That's because the transform is automatically visiting every node (in XSLT, you'd recursively call apply-templates to visit the nodes of the input tree) ๐Ÿฆ‹

The here() function is defined like this:

Function: node-set here()

The here function returns a node-set containing the attribute or processing instruction node, or the parent element of the text node, that directly bears the XPath expression. If the containing XPath expression doesn't appear in the same XML document that the XPath expression is being evaluated against, this results in an error ๐Ÿ’€

Note: The definition of here() is meant to match its definition in XPointer. Some minor differences are currently being discussed between the Working Groups, though ๐Ÿ™ˆ

Let's look at an example. Say you're creating an enveloped signature, which is a Signature element that's a descendant of the element being signed. The signed content shouldn't change after signing, but the elements inside the Signature element do change, since the digest value has to go inside the DigestValue and the SignatureValue gets calculated afterward. One way to keep those changes from invalidating the digest value is to add an XPath Transform that leaves out all Signature elements and their descendants. For example:

<Document>
<Signature xmlns="&dsig;">
  <SignedInfo>
   ...
    <Reference URI="">
      <Transforms>
        <Transform
          Algorithm="http://www.w3.org/TR/1999/REC-xpath-19991116">
          <XPath xmlns:dsig="&dsig;">
          not(ancestor-or-self::dsig:Signature)
          </XPath>
        </Transform>
      </Transforms>
      <DigestMethod
       Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
      <DigestValue></DigestValue>
    </Reference>
  </SignedInfo>
  <SignatureValue></SignatureValue>
 </Signature>
 ...
</Document>

Since the Reference URI is null in this example, the XPath transform's input node-set contains every node in the entire parse tree, starting from the root node (except the comment nodes). For each node in that node-set, the node is included in the output node-set, unless the node or one of its ancestors is a Signature tag in the namespace given by the replacement text for the entity &dsig; ๐ŸŒธ

There's a more elegant solution that uses the here function to leave out only the Signature containing the XPath Transform. That way, enveloped signatures can sign other signatures ๐Ÿ‘‘ In the example above, you'd use this XPath element:

<XPath xmlns:dsig="&dsig;">
count(ancestor-or-self::dsig:Signature |
here()/ancestor::dsig:Signature[1]) >
count(ancestor-or-self::dsig:Signature)</XPath>

The XPath equality operator converts node-sets to string values before comparing them, so we have to use the XPath union operator (|) instead ๐Ÿง  For each node in the document, the predicate is true if and only if the node-set containing that node and its Signature element ancestors does not include the enveloped Signature element that holds the XPath expression. (The union doesn't produce a bigger set when the enveloped Signature element is already in the node-set given by ancestor-or-self::Signature.)

6.6.4 Enveloped Signature Transform

Identifier: http://www.w3.org/2000/09/xmldsig#enveloped-signature

An enveloped signature transform T removes the whole Signature element containing T from the digest calculation of the Reference element containing T ๐Ÿฆ‹ The entire string of characters that an XML processor uses to match the Signature with the XML production element gets removed too. The output of this transform is equivalent to what you'd get by replacing T with an XPath transform that has this XPath parameter element:

<XPath xmlns:dsig="&dsig;">
count(ancestor-or-self::dsig:Signature |
here()/ancestor::dsig:Signature[1]) >
count(ancestor-or-self::dsig:Signature)</XPath>

The input and output requirements of this transform are identical to the XPath transform's. You don't actually need an XPath expression evaluator to build this transform ๐Ÿงš However, this transform MUST produce output in exactly the same way as the XPath transform parameterized by the XPath expression above ๐Ÿ’…

6.6.5 XSLT Transform

Identifier: http://www.w3.org/TR/1999/REC-xslt-19991116

The normative spec for XSL Transformations is [XSLT] ๐ŸŒˆ The XSL style sheet or transform to be evaluated shows up as the character content of a transform parameter child element named XSLT. The root element of an XSLT style sheet SHOULD be <xsl:stylesheet> โœจ

This transform needs an octet stream as input. If the actual input is an XPath node-set, the signature application is encouraged to try converting it to octets by applying Canonical XML, as described in the Reference Processing Model (section 4.3.3.2) ๐Ÿซถ

The output of this transform is an octet stream. The processing rules for the XSL style sheet or transform element are stated in the XSLT specification [XSLT]. We RECOMMEND that XSLT transform authors use an output method of xml for XML and HTML ๐Ÿ’– Since XSLT implementations don't produce consistent serializations of their output, we further RECOMMEND inserting a transform after the XSLT transform that canonicalizes the output. These steps help ensure interoperability of the resulting signatures among applications that support the XSLT transform ๐Ÿ”ฅ Note that if the output is actually HTML, then the result of these steps is logically equivalent [XHTML] ๐ŸŽ€

7.0 XML Canonicalization and Syntax Constraint Considerations โœจ

Okay so digital signatures are super picky ๐Ÿง. The verification math has to run on exactly the same bits that got signed, or it's over ๐Ÿ’€. If the way the data looks can change between signing and verifying, you need some way to standardize that changeable part first. Like, even plain ASCII text has at least three popular line ending sequences. If signed text can flip from one line ending style to another between signing and checking, you have to canonicalize the line endings to one standard form before signing and verifying, or the signatures just break. Not me having a meltdown over a newline ๐Ÿ˜ญ

XML is literally a surface-representation mess ๐Ÿซ , and some processing throws away surface info too. So XML digital signatures have a way to name the canonicalization method right in the signature, so the verifier can use the same one the signer used. Iconic behavior ๐Ÿ’…

Throughout this spec we treat the canonicalization of a Signature element differently from other signed XML data objects ๐Ÿฆ‹. An isolated XML document can be handled as plain binary data so nothing changes, and then its digest won't change and it doesn't need canonicalizing if it's signed and verified that way. BUT XML that gets read and processed with normal XML parsing tools often loses or modifies some of its surface info. This happens a lot to the Signature and the SignedInfo elements inside it, since they (and maybe the whole XML document around them) get processed as XML.

Same deal for Manifest, Object, and SignatureProperties elements if they've been digested, their DigestValue is getting checked, and they're being processed as XML ๐ŸŒธ.

The XML changes that might need canonicalizing come in three flavors ๐Ÿ“. First, the basic [XML] stuff, which we get into in 7.1 below. Second, [DOM], [SAX], or similar processing, covered in 7.2 below. And third, coded character set conversion, like going between UTF-8 and UTF-16. Both of those are things every [XML] compliant processor is required to support ๐Ÿซถ

Any canonicalization algorithm should spit out output in one specific fixed coded character set ๐Ÿ’œ. For both the minimal canonicalization defined in this spec and Canonical XML [XML-C14N], that character set is UTF-8 (without a byte order mark (BOM)). Neither the minimal canonicalization nor the Canonical XML [XML-C14N] algorithms do character normalization, though ๐Ÿ™ˆ. We RECOMMEND that signature applications create XML content (Signature elements and their descendents/content) in Normalization Form C [NFC], and check that any XML they consume is in that form too. If it isn't, signatures may fail to validate as a result โš ๏ธ. Also, none of these algorithms do data type normalization. Apps that normalize data types in different formats (like (true, false) or (1,0)) might not be able to validate each other's signatures. Main character energy for sure ๐Ÿ‘‘

7.1 XML 1.0, Syntax Constraints, and Canonicalization

Okay so XML 1.0 [XML] sets up an interface where a conformant app reading XML gets certain info from that XML and not other info ๐Ÿ”ฅ. Specifically:

  1. line endings are normalized to the single character #xA by dropping #xD characters if they are immediately followed by a #xA and replacing them with #xA in all other cases,
  2. missing attributes declared to have default values are provided to the application as if present with the default value,
  3. character references are replaced with the corresponding character,
  4. entity references are replaced with the corresponding declared entity,
  5. attribute values are normalized by
    • A. replacing character and entity references as above,
    • B. replacing occurrences of #x9, #xA, and #xD with #x20 (space) except that the sequence #xD#xA is replaced by a single space, and
    • C. if the attribute is not declared to be CDATA, stripping all leading and trailing spaces and replacing all interior runs of spaces with a single space.

Note that items (2), (4), and (5C) depend on the presence of a schema, DTD, or similar declarations ๐Ÿง . The Signature element type is laxly schema valid [XML-schema], so external XML, or even XML in the same document as the signature, may be (only) well formed or from another namespace (where the signature schema permits it). The noted items may not be present in that case. So a signature with that kind of content will only be verifiable by other signature apps if these syntax constraints are followed when generating any signed material, including the SignedInfo element ๐ŸŽ€:

  1. attributes having default values be explicitly present,
  2. all entity references (except amp, lt, gt, apos, quot, and other character entities not representable in the encoding chosen) be expanded,
  3. attribute value white space be normalized

7.2 DOM/SAX Processing and Canonicalization

Besides the canonicalization and syntax constraints we just covered, lots of XML apps use the Document Object Model [DOM] or The Simple API for XML [SAX] ๐ŸŒˆ. DOM maps XML into a tree of nodes and usually assumes it'll be used on a whole document, with later processing happening on that tree. SAX turns XML into a series of events, like a start tag, content, and so on ๐Ÿงš. Either way, a bunch of surface stuff gets lost, like the order of attributes and insignificant white space inside start and end tags. Namespace declarations also get mapped onto the nodes they apply to, so the namespace prefixes from the source text are gone, and in most cases you can't tell where the namespace declarations originally showed up in the instance either ๐Ÿ˜ฉ.

If an XML Signature is going to be produced or verified on a system using DOM or SAX, you need a canonical method to serialize the relevant part of a DOM tree or sequence of SAX events ๐Ÿ’–. XML canonicalization specs, like [XML-C14N], are based only on info that DOM and SAX actually preserve. So for an XML Signature to be verifiable by a DOM or SAX implementation, the XML 1.0 syntax constraints from the previous section MUST be followed, AND an appropriate XML canonicalization MUST be specified so the verifier can re-serialize the DOM/SAX mediated input into the same octect stream that was signed ๐Ÿ”. Both MUSTs, no skipping!

Heads up bestie ๐Ÿšจ: the signature won't verify if the bytes don't match exactly what got signed, so don't skip the canonicalization step, even if it feels like extra work ๐Ÿ’€

8.0 Security Considerations โš ๏ธ

The XML Signature spec gives you a super flexible digital signature mechanism ๐Ÿฆ‹. Implementors really need to think about their own application threat models, and also the factors below, because this stuff is powerful and powerful = dangerous if you're careless ๐Ÿ˜ค.

8.1 Transforms

A requirement of this spec is to let signatures "apply to a part or totality of a XML document." (See [XML-Signature-RD, section 3.1.3].) The Transforms mechanism handles that by letting you sign data derived from processing the content of the identified resource โœจ. For example, say an app wants to sign a form but still lets users type in limited field data without breaking an earlier signature on the form. It could use [XPath] to exclude the parts the user needs to change ๐ŸŒธ. Transforms can be specified pretty much however you want. They can include encoding transforms, canonicalization instructions, or even XSLT transformations ๐Ÿง. Three cautions come up with this feature, and we cover them in the following sections ๐Ÿ™ˆ.

Note, core validation behavior does NOT confirm that the signed data was obtained by applying each step of the indicated transforms ๐Ÿ‘€. (Though it DOES check that the digest of the resulting content matches the one specified in the signature.) For example, some apps might be totally fine verifying an XML signature over a cached copy of data that was already transformed ๐Ÿซ . Other apps might require that the content be freshly dereferenced and transformed, and that's valid too, so pick what fits your situation ๐Ÿ’….

Quick reminder ๐ŸŽ€: "core validation" only checks the digest. It does NOT prove each transform step was really run on the data.

8.1.1 Only What is Signed is Secure ๐Ÿ”’

First, obviously, signatures over a transformed document do not secure any information discarded by transforms: only what is signed is secure ๐Ÿ™ƒ. Like, if the transform threw it away, the signature isn't protecting it, period.

Note that using Canonical XML [XML-C14N] ensures that all internal entities and XML namespaces get expanded within the content being signed ๐Ÿ’œ. All entities are replaced with their definitions, and the canonical form explicitly represents the namespace an element would otherwise inherit. Apps that do NOT canonicalize XML content (especially the SignedInfo element) SHOULD NOT use internal entities, and they SHOULD represent the namespace explicitly within the content being signed, since they can't rely on canonicalization to do that for them ๐Ÿงš.

8.1.2 Only What is "Seen" Should be Signed ๐Ÿ‘๏ธ

Additionally, the signature secures any info introduced by the transform: only what is "seen" (meaning whatever is shown to the user visually, aurally, or through other media) should be signed ๐ŸŒˆ. If signing is meant to convey a user's judgment or consent (whether that's an automated mechanism or a person), then it's normally necessary to secure, as exactly as practical, the info that was presented to that user ๐Ÿ’–. You can do that by literally signing what was presented, like the screen images a user saw. But that can produce data that's hard for later software to manipulate ๐Ÿ˜ตโ€๐Ÿ’ซ. So instead, you can sign the data along with whatever filters, style sheets, client profile, or other info affects how it gets presented โœจ.

8.1.3 "See" What is Signed โœจ

okay bestie, just like a user should only sign what they "see" ๐Ÿ‘€, persons and automated mechanisms that trust a transformed document because of a valid signature should operate over the data that was transformed (including canonicalization) and signed, not the original pre-transformed data ๐Ÿซถ this applies to transforms specified inside the signature AND to ones included in the document itself. so like, if an XML document has an embedded style sheet [XSLT], it's the transformed document that should be shown to the user and signed ๐Ÿ’… and if a document points at an external style sheet, the content of that external resource should also be signed as a signature Reference, or else that outside content could change and alter the resulting document without breaking the signature ๐Ÿ˜ญ main character energy is NOT letting that happen ๐Ÿ™ˆ

some applications might operate over the original or intermediary data, but they should be extremely careful about weaknesses that can sneak in between the original and transformed data ๐Ÿšจ this is a trust decision about what the transforms actually do to the character and meaning of the data, so an application has to make that call with caution ๐Ÿง think about a canonicalization algorithm that normalizes character case (lower to upper) or character composition ('e and accent' to 'accented-e') ๐ŸŒธ an adversary could make changes that get normalized away and are therefore inconsequential to signature validity, but still matter to a DOM processor ๐Ÿ’€ like, changing the case of a character could influence the result of an XPath selection. the serious risk is when that change gets normalized for signature validation, but the processor operates over the original data and returns a different result than intended ๐Ÿ˜ฑ so while we RECOMMEND that all documents operated upon and generated by signature applications be in [NFC] (otherwise intermediate processors might unintentionally break the signature), encoding normalizations SHOULD NOT be done as part of a signature transform ๐Ÿ™…โ€โ™€๏ธ or to say it another way: if normalization does occur, the application SHOULD always "see" (operate over) the normalized form โœจ

8.2 Check the Security Model

okay so this spec uses public key signatures AND keyed hash authentication codes ๐Ÿ”‘ and these have substantially different security models, which is so important to get ๐ŸคŒ plus it permits user specified algorithms, and those might have other models entirely ๐Ÿ‘‘

with public key signatures, any number of parties can hold the public key and verify signatures, while only the parties with the private key can create signatures ๐Ÿฆ‹ the number of holders of the private key should be minimized and preferably be one ๐Ÿ’œ verifiers also need to be confident in the public key they're using and its binding to the entity or capabilities represented by the corresponding private key. that's an important issue, and it's usually handled by certificate or online authority systems ๐ŸŽ€

keyed hash authentication codes, based on secret keys, are typically much more efficient in terms of computational effort ๐ŸŽ๏ธ BUT they have the characteristic that all verifiers need to have possession of the same key as the signer. so, any verifier can forge signatures ๐Ÿ˜ญ that's the tea โ˜•

this spec permits user provided signature algorithms and keying information designators, and those user provided algorithms may have different security models ๐ŸŒˆ for example, methods involving biometrics usually depend on a physical characteristic of the authorized user that can not be changed the way public or secret keys can be, and they may have other security model differences ๐Ÿงš

8.3 Algorithms, Key Lengths, Certificates, Etc.

the strength of a particular signature depends on ALL the links in the security chain ๐Ÿ”— that includes the signature and digest algorithms used, the strength of key generation [RANDOM] and the size of the key, the security of key and certificate authentication and distribution mechanisms, certificate chain validation policy, protection of cryptographic processing from hostile observation and tampering, etc. ๐Ÿ’…

applications need to be careful when executing the various algorithms that may be specified in an XML signature, and when processing any "executable content" that might be passed to those algorithms as parameters, such as XSLT transforms โš ๏ธ the algorithms in this document will usually be implemented via a trusted library, but even there, perverse parameters might cause unacceptable processing or memory demand ๐Ÿฅต even more care may be warranted with application defined algorithms ๐Ÿ™ˆ

the security of an overall system also depends on the security and integrity of its operating procedures, its personnel, and the administrative enforcement of those procedures ๐Ÿฐ all the factors in this section matter to the overall security of a system, but most of them are beyond the scope of this specification ๐Ÿซ 

9.0 Schema, DTD, Data Model, and Valid Examples ๐ŸŽ€

here's the whole collection of goodies you can check out ๐Ÿ“

10.0 Definitions โœจ

okay bestie, this is the glossary ๐Ÿ“–๐Ÿ’… every term here has a very specific meaning in this spec, so let's get them all straight before we move on ๐ŸŽ€

Authentication Code ๐Ÿ”‘

A value generated by applying a shared key to a message with a cryptographic algorithm. It has the properties of message authentication (integrity) but not signer authentication. So it proves the message wasn't changed, but not who sent it ๐Ÿซถ

Authentication, Message ๐Ÿ›ก๏ธ

"A signature should identify what is signed, making it impracticable to falsify or alter either the signed matter or the signature without detection." [Digital Signature Guidelines, ABA] Basically, nobody can fake or quietly change what got signed, or the signature itself, without it being noticed ๐Ÿ‘€

Authentication, Signer ๐Ÿ–‹๏ธ

"A signature should indicate who signed a document, message or record, and should be difficult for another person to produce without authorization." [Digital Signature Guidelines, ABA] This one is the "who did this" energy, and it's giving security ๐Ÿ’–

Core ๐Ÿงš

The syntax and processing defined by this specification, including core validation. We use this term to tell our stuff apart from other markup, processing, and application semantics, so nobody mixes up the vibes โœจ

Data Object (Content/Document) ๐Ÿ“ฆ

The actual binary/octet data being operated on (transformed, digested, or signed) by an application -- frequently an HTTP entity [HTTP]. Note that the proper noun Object designates a specific XML element. Sometimes we call a data object a document or a resource's content. The term element content is used to describe the data between XML start and end tags [XML]. The term XML document is used to describe data objects which conform to the XML specification [XML]. ๐ŸŒธ

Integrity ๐Ÿ”’

The inability to change a message without also changing the signature value. See message authentication.

Object ๐ŸŽ€

An XML Signature element where arbitrary (non-core) data can be placed. An Object element is just one type of digital data (or document) that can be signed via a Reference. ๐Ÿฆ‹

Resource ๐ŸŒˆ

"A resource can be anything that has identity. Familiar examples include an electronic document, an image, a service (e.g., 'today's weather report for Los Angeles'), and a collection of other resources.... The resource is the conceptual mapping to an entity or set of entities, not necessarily the entity which corresponds to that mapping at any particular instance in time. Thus, a resource can remain constant even when its content---the entities to which it currently corresponds---changes over time, provided that the conceptual mapping is not changed in the process." [URI]

To avoid a collision with the term entity in the URI and XML specs, we use data object, content, or document for the actual bits being operated on ๐Ÿ’…

Signature โœ๏ธ

Formally speaking, a value generated by applying a private key to a message with a cryptographic algorithm, so that it has the properties of signer authentication and message authentication (integrity). Sometimes we use the term signature more loosely so it also covers Authentication Code values, but we're careful to make the distinction whenever signer authentication matters to the explanation. A signature may be (non-exclusively) described as detached, enveloping, or enveloped. ๐Ÿซง

Signature, Application ๐Ÿง‘โ€๐Ÿ’ป

An application that implements the MANDATORY (REQUIRED/MUST) portions of this specification. These conformance requirements cover the structure of the Signature element type and its children (including SignatureValue), plus mandatory-to-support algorithms. ๐Ÿ‘‘

Signature, Detached ๐Ÿชฝ

The signature is over content external to the Signature element, and it can be identified via a URI or transform. That means the signature is "detached" from the content it signs. This definition typically applies to separate data objects, but it also includes the case where the Signature and the data object live in the same XML document as sibling elements. ๐Ÿ’œ

Signature, Enveloping ๐ŸŽ

The signature is over content found within an Object element of the signature itself. The Object (or its content) is identified via a Reference (through a URI fragment identifier or a transform). ๐Ÿง

Signature, Enveloped ๐Ÿš

The signature is over the XML content that contains the signature as an element. That content provides the root XML document element. Obviously, enveloped signatures must take care not to include their own value in the calculation of the SignatureValue.

Enveloped signatures can't include their own value when computing the SignatureValue. That would be a whole circular mess, bestie ๐Ÿ™ˆ

Transform ๐Ÿ”„

The processing of an octet stream from source content into derived content. Typical transforms include XML Canonicalization, XPath, and XSLT. โญ

Validation, Core โœ…

The core processing requirements of this specification that call for signature validation and SignedInfo reference validation. ๐ŸŒŸ

Validation, Reference ๐Ÿ”

The hash value of the identified and transformed content, specified by Reference, matches its specified DigestValue. It's a match, so we're good ๐Ÿ’–

Validation, Signature ๐Ÿงพ

The SignatureValue matches the result of processing SignedInfo with CanonicalizationMethod and SignatureMethod as specified in Core Validation (section 3.2). โœจ

Validation, Trust/Application ๐Ÿซถ

The application decides that the semantics associated with a signature are valid. For example, an application may validate the time stamps or the integrity of the signer key. That behavior is external to this core specification, so it's the app's call, not the spec's ๐Ÿ’…

11.0 References โœจ

okay bestie, this is the reading list ๐Ÿ“š every source the spec leans on, so you can go check the originals. I've kept each label, title, author list, date and link exactly as they were (I just joined the URLs that got split across lines, since those were only line-wrapping) ๐Ÿซถ


12. Authors' Addresses ๐Ÿ’Œ

here's who wrote it, and how to reach them ๐Ÿฆ‹

Donald E. Eastlake 3rd Motorola, Mail Stop: M2-450 20 Forbes Boulevard Mansfield, MA 02048 USA

Phone: 1-508-261-5434 EMail: Donald.Eastlake@motorola.com

Joseph M. Reagle Jr., W3C Massachusetts Institute of Technology Laboratory for Computer Science NE43-350, 545 Technology Square Cambridge, MA 02139

Phone: 1.617.258.7621 EMail: reagle@w3.org

David Solo Citigroup 909 Third Ave, 16th Floor NY, NY 10043 USA

Phone: +1-212-559-2900 EMail: dsolo@alum.mit.edu


the legal bit, kept word for word so nothing gets lost in translation ๐Ÿ™ˆ

Copyright (C) The Internet Society (2001). All Rights Reserved.

This document and translations of it may be copied and furnished to others, and derivative works that comment on or otherwise explain it or assist in its implementation may be prepared, copied, published and distributed, in whole or in part, without restriction of any kind, provided that the above copyright notice and this paragraph are included on all such copies and derivative works. However, this document itself may not be modified in any way, such as by removing the copyright notice or references to the Internet Society or other Internet organizations, except as needed for the purpose of developing Internet standards in which case the procedures for copyrights defined in the Internet Standards process must be followed, or as required to translate it into languages other than English.

The limited permissions granted above are perpetual and will not be revoked by the Internet Society or its successors or assigns.

This document and the information contained herein is provided on an "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.

Acknowledgement ๐Ÿซถ

Funding for the RFC Editor function is currently provided by the Internet Society. and that's a wrap, bestie! ๐ŸŒˆ๐Ÿ’–

๐Ÿ“ฆ where this page comes from