Some strawman ideas for a minimum DSig profile

Hi Everyone,

Brian took an action item at the F2F (ACTION-15) to propose a means of
identifying to-be-processed elements, and Kelvin took an action item at the
last conference call (ACTION-21) to propose a method to reduce the attack
surface.  Since these two items are related we've come up with a joint
strawman proposal for how we could identify that an XMLDSIG complies with
a "minimum profile" and the elements within that need to be hashed.

One of the problems with XMLDSIG is that even a minimum profile of XMLDSIG
requires (as a practical matter) the use of an XML DOM with XPath 1.0 support,
but this is somewhat counter-intuitive. Ideally, applications should be able
to lower risk by verifying the source and integrity of an XML message first
with minimal processing.  Once verified, then a full XML stack (with a larger
attack surface) may be leveraged.

In order to reduce the attack surface to a minimum, it must be possible for
the verifier to do little more than compute cryptographic hashes and perform
signature verification, which implies that a new minimum profile of XMLDSIG
cannot require the verifier to perform XPath-based canonicalization. To do
this while maintaining compatibility, the responsibility must shift to the
signer to "pre-canonicalize" the signed elements. (This also means that, at
least in a minimum profile, it would not be possible to sign arbitrary
node-sets that cannot themselves be expressed as an XML fragment.)

To indicate the new semantics while maintaining compatibility with the
existing XMLDSIG schema, we proposed to introduce a new XML processing
instruction (tentatively named "xml-min-disg" for now). Konrad suggested
using a PI at the F2F, and after looking at the situation it is the only
approach we could come up with that would allow us to add semantics to the
existing XMLDSIG schema without breaking it.  While use of PIs is not ideal,
and some standards (e.g. WS-Security) specifically disallow PIs at certain
locations in their schema, it is the only method available. As a side benefit,
the use of the proposed PI will also allow an XMLDSIG processor to perform
one-pass validation.

For example, consider the following signed XML that uses only Canonical XML 1.1:

  <?xml version="1.0" encoding="utf-8"?>
  <k:Root xmlns:k="http://www.example.com/2008/08/k#"
      xmlns:xml="http://www.w3.org/XML/1998/namespace">
    <k:Node1 xml:id="k1">
      <k:Text>sample text</k:Text>
    </k:Node1>
    <k:Node1 xml:id="k2">
      <k:Text>More sample text</k:Text>
    </k:Node1>
    <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
      <ds:SignedInfo>
        <ds:CanonicalizationMethod
            Algorithm="http://www.w3.org/2006/12/xml-c14n11"/>
        <ds:SignatureMethod
            Algorithm="http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256"/>
        <ds:Reference URI="#k1" Id="Sig1Ref1">
          <ds:Transforms>
            <ds:Transform Algorithm="http://www.w3.org/2006/12/xml-c14n11"/>
          </ds:Transforms>
          <ds:DigestMethod
              Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
          <ds:DigestValue>...</ds:DigestValue>
        </ds:Reference>
      </ds:SignedInfo>
      <ds:SignatureValue>...</ds:SignatureValue>
      <ds:KeyInfo>...</ds:KeyInfo>
    </ds:Signature>
  </k:Root>

A signer who wants to maintain backwards compatibility would generate the
following:

  <?xml version="1.0" encoding="utf-8"?>
  <?xml-min-dsig version="1.0"?>
  <k:Root xmlns:k="http://www.example.com/2008/08/k#"
      xmlns:xml="http://www.w3.org/XML/1998/namespace">
    <?xml-min-dsig
        URI="#k1"
        ref-id="Sig1Ref1"
        digest-algorithm="http://www.w3.org/2001/04/xmlenc#sha256"?>
    <k:Node1 xml:id="k1" xmlns:k="http://www.example.com/2008/08/k#"
        xmlns:xml="http://www.w3.org/XML/1998/namespace">
      <k:Text>sample text</k:Text>
    </k:Node1>
    <k:Node1 xml:id="k2">
      <k:Text>More sample text</k:Text>
    </k:Node1>
    <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
      <?xml-min-dsig
          digest-algorithm="http://www.w3.org/2001/04/xmlenc#sha256"?>
      <ds:SignedInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
        <ds:CanonicalizationMethod
            Algorithm="http://www.w3.org/2006/12/xml-c14n11"/>
        <ds:SignatureMethod
            Algorithm="http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256"/>
        <ds:Reference URI="#k1" Id="Sig1Ref1">
          <ds:Transforms>
            <ds:Transform
                Algorithm="http://www.w3.org/2006/12/xml-c14n11"/>
          </ds:Transforms>
          <ds:DigestMethod
              Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
          <ds:DigestValue>...</ds:DigestValue>
        </ds:Reference>
      </ds:SignedInfo>
      <ds:SignatureValue>...</ds:SignatureValue>
      <ds:KeyInfo>...</ds:KeyInfo>
    </ds:Signature>
  </k:Root>

In a nutshell, the presence of the xml-min-dsig PI indicates that the
following element node will be processed with the new semantics of the
minimum profile. The first xml-min-dsig PI (before the k:Root element)
indicates the entire document follows the new semantics, which may be
useful if we want to allow implementations to reject non-compliant XML
quickly.

The 2nd xml-min-dsig PI (before the k:Node1 element) indicates to the XMLDSIG
implementation to hash the entire <k:Node1> element. The hash algorithm is
indicated by "digest-algorithm" with URIs. The variable "ref-id" is used by a
XMLDSIG processor to locate a specific <Reference> element, while the variable
URI allows the XMLDSIG processor to perform the id match. The computed hash
must match with the value stored in the matching <Reference> element. The
<Transforms> element is ignored.

The 3rd xml-min-dsig PI, located between the <Signature> and <SignedInfo>
elements, is not strictly necessary but will allow an XMLDSIG processor to
start hashing <SignedInfo> immediately without parsing the <SignatureMethod>
element.

When backwards compatibility is not needed, the signer may generate the
following instead. Notice the empty URI to indicate no further
canonicalization is needed.

  <?xml version="1.0" encoding="utf-8"?>
  <?xml-min-dsig version="1.0"?>
  <k:Root xmlns:k="http://www.example.com/2008/08/k#"
      xmlns:xml="http://www.w3.org/XML/1998/namespace">
    <?xml-min-dsig
        URI="#k1"
        ref-id="Sig1Ref1"
        digest-algorithm="http://www.w3.org/2001/04/xmlenc#sha256"?>
    <k:Node1 xml:id="k1">
      <k:Text>sample text</k:Text>
    </k:Node1>
    <k:Node1 xml:id="k2">
      <k:Text>More sample text</k:Text>
    </k:Node1>
    <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
      <?xml-min-dsig
          digest-algorithm="http://www.w3.org/2001/04/xmlenc#sha256"?>
      <ds:SignedInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
        <ds:CanonicalizationMethod Algorithm=""/>
        <ds:SignatureMethod
            Algorithm="http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256"/>
        <ds:Reference URI="#k1" Id="Sig1Ref1">
          <ds:DigestMethod
            Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
          <ds:DigestValue>...</ds:DigestValue>
        </ds:Reference>
      </ds:SignedInfo>
      <ds:SignatureValue>...</ds:SignatureValue>
      <ds:KeyInfo>...</ds:KeyInfo>
    </ds:Signature>
  </k:Root>


Thoughts?

Kelvin and Brian


Sample disclaimer text

Received on Tuesday, 12 August 2008 00:24:23 UTC