OASIS ebXML Messaging Services TC

 View Only

[ebxml-msg] Whitespace problem with XMLDSIG usage in ebMSS

  • 1.  [ebxml-msg] Whitespace problem with XMLDSIG usage in ebMSS

    Posted 12-19-2001 01:39
    Hi,
    
    This email analyzes a limitation of the way XMLDSIG is currently used in the
    ebXML Message Service
    Specification (ebMSS) v1.0.91 and proposes a solution to overcome that
    limitation.
    
    ebMSS dictates how XMLDSIG must be used by conforming MSH implementations.
    Unfortunately, a
    signature generated in accordance with the current ebMSS specification is
    very sensitive to trivial
    changes in whitespace (space, CR, LF and tab characters) in the xml content.
    For example, if the
    xml structure of the eb:To element (in some ebXML envelope) is changed from:
    
      <eb:To><eb:PartyId type='some-type'>CompanyA</eb:PartyId></eb:To>
    
    to
    
      <eb:To>
        <eb:PartyId type='some-type'>CompanyA</eb:PartyId>
      </eb:To>
    
    a signature created over the first representation becomes invalid.  This is
    because the extra CRLF
    and other whitespace characters (in the second representation) affect the
    digest, even though this
    change in surface representation does not affect the meaning of the message.
    The soap and ebXML
    schemas define such whitespace characters as being irrelevant.  Both the
    above examples will
    validate against the schema.  However, the way XMLDSIG is being used in
    ebMSS, every whitespace
    character is important.  In a way, the signature is being too restrictive to
    trivial changes in the
    envelope.
    
    A first (and reasonable) reaction would be, should not the canonicalization
    transform (required by
    line 1108, ebMSS) already take care of this possiblity?  Canonical XML
    (defined by
    http://www.w3.org/TR/2001/REC-xml-c14n-20010315), however does not take care
    of this and (correctly)
    regards all textual content (whitespace or not) as being significant
    (meaningful) (section 3.2 of
    Canonical XML).  That is because, without a schema or DTD, it is not
    possible to know which
    whitespace is signficant and which is not and the transform described by
    Canonical XML does not use
    the DTD or schema to decide whether a particular whitespace character is
    significant or not.
    
    This problem specifically affects intermediary MSHs.  It is unreasonable to
    expect such an MSH to
    preserve irrelevant whitespace when forwarding an ebXML message.  On the
    other hand, if such
    whitespace is unintentionally changed, any signature introduced by the
    sender becomes invalid.
    
    This problem can manifest itself even in an MSH that is not an intermediary.
    An unthinking MSH
    implementer might pretty print outgoing ebXML messages but performing pretty
    printing after the
    signature has been computed would invalidate the signature. If the signature
    is tolerant of changes
    in whitespace, pretty printing could be the final step (after signing).
    Granted, pretty printing is
    not a requirement but the examples in ebMSS would lead an implementer to
    believe that ebXML messages
    should be pretty printed.
    
    The proposed solution applies an XMLDSIG transform to the ebXML envelope
    before signing (and before
    verification) so that trivial changes in whitespace is eliminated.
    
    Of the various transforms XMLDSIG defines, this proposal uses the XSL
    transform to eliminate
    insignificant whitespace.
    
    ebMSS currently requires the following ds:Transforms element to be used when
    signing the envelope.
    
      <Transforms>
        <Transform
    Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
        <Transform Algorithm="http://www.w3.org/TR/1999/REC-xpath-19991116">
          <XPath>
     
    not(ancestor-or-self::*[@SOAP:actor="urn:oasis:names:tc:ebxml-msg:service:ne
    xtMSH"] |
     
    ancestor-or-self::*[@SOAP:actor="http://schemas.xmlsoap.org/soap/actor/next"
    ])
          </XPath>
        </Transform>
        <Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
      </Transforms>
    
    By adding another ds:Transform element, resilience to changes in surface
    representation can be achieved:
    
      <Transforms>
        <Transform
    Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
        <Transform Algorithm="http://www.w3.org/TR/1999/REC-xpath-19991116">
          <XPath>
     
    not(ancestor-or-self::*[@SOAP:actor="urn:oasis:names:tc:ebxml-msg:service:ne
    xtMSH"] |
     
    ancestor-or-self::*[@SOAP:actor="http://schemas.xmlsoap.org/soap/actor/next"
    ])
          </XPath>
        </Transform>
        <Transform Algorithm="http://www.w3.org/TR/1999/REC-xslt-19991116">
          <xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
            <xsl:strip-space elements='*'/>        <!-- Strip whitespace. -->
            <xsl:template match='node()|@*'>       <!-- The identity transform.
    -->
              <xsl:copy> <xsl:apply-templates select='@*'/>
    <xsl:apply-templates/> </xsl:copy>
            </xsl:template>
          </xsl:stylesheet>
        </Transform>
        <Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
      </Transforms>
    
    The newly added (XSL) transform instructs the xmldsig processor to apply the
    inlined stylesheet to
    the output of the enveloping transform before passing it on to the xpath
    transform.  The stylesheet
    itself is a simple variation on the identity transform.  If an element is
    specified in
    <xsl:strip-space> ( '*' specifies all elements), and ALL the text node
    children of that element are
    whitespaces, then these whitespace text nodes are stripped (trimmed).  In
    other words, if an element
    contains non-whitespace textual content interspersed with whitespace, NO
    whitespace is removed (this
    last point is elaborated on later).
    
    The following example tries to explain.  This snippet from some ebXML
    message:
    
      <eb:To>
        <eb:PartyId type='some-type'>CompanyA</eb:PartyId>
      </eb:To>
    
      <eb:CPAId>CompanyA-CompanyB</eb:CPAId>
    
    is transformed to:
    
    <eb:To><eb:PartyId
    type='some-type'>CompanyA</eb:PartyId></eb:To><eb:CPAId>CompanyA-CompanyB</e
    b:CPAId>
    
    Notice that the whitespace contained by eb:To and between eb:To and eb:CPAId
    has been eliminated.
    
    On the other hand, this snippet
    
      <eb:Description xml:lang="en-US">
      	This textual content
    		contains whitespace
    	but is left untouched.
      </eb:Description>
    
    remains unchanged:
    
      <eb:Description xml:lang="en-US">
      	This textual content
    		contains whitespace
    	but is left untouched.
      </eb:Description>
    
    The latter example illustrates the point that if an element contains ANY
    non-whitespace textual
    content, NO whitespace is eliminated.  Or, in other words, if an element
    contains non-whitespace
    textual content, all sibling whitespace is automatically considered
    significant.  This conveniently
    meets the intuitive requirement that an intermediary MSH should not modify
    an eb:Description
    element, even if the modification is limited to whitespace.
    
    One limitation of the XSL transform as presented above, is a result of what
    seems like an XMLDSIG
    problem and something that the XMLDSIG folks are being made aware of.
    Specifically, the
    ds:SignedInfo element (child of ds:Signature) is outside the scope of the
    above XSL transform (it is
    not processed by the latter) and hence, ds:SignedInfo is not robust to
    changes in whitespace. The
    ds:Signature element structure typically looks like (pardon the verbosity):
    
      <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
        <ds:SignedInfo>
          <ds:CanonicalizationMethod
    Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
          <ds:SignatureMethod
    Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
          <ds:Reference URI="">
            <ds:Transforms>
              <ds:Transform
    Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
              <ds:Transform
    Algorithm="http://www.w3.org/TR/1999/REC-xpath-19991116">
     
    <ds:XPath>not(ancestor-or-self::node()[@SOAP-ENV:actor=&quot;urn:oasis:names
    :tc:ebxml-msg:actor:nextMSH&quot;]
    	  |
    ancestor-or-self::node()[@SOAP-ENV:actor=&quot;http://schemas.xmlsoap.org/so
    ap/actor/next&quot;])</XPath>
              <ds:/Transform>
              <ds:Transform
    Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
            <ds:/Transforms>
            <ds:DigestMethod
    Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
            <ds:DigestValue>JklY0tWheXRXBlYIbS7pY9bYGdY=</DigestValue>
          <ds:/Reference>
        <ds:/SignedInfo>
        <ds:SignatureValue>
     
    fsgBjrgjg7u6+Nxwqa1GTKY3AkvORTygCmoXDMIGveiUkmNZ2L4DDgbD6FhGVNMvKVfzsKxv
     
    LRhBV2QW1YsOH+Ot8BpB49lcHdmweMIApbXo0Y+uKe4t73YGE7QAuboLaCQQQ+X++MCu6uzC
          YVnA3zHTuZiEz+qABxbFRgQg20g=
        <ds:/SignatureValue>
      <ds:/Signature>
    
    The only processing that the ds:SignedInfo is subject to, prior to
    verification is the algorithm
    specified by ds:CanonicalizationMethod
    (http://www.w3.org/TR/2001/REC-xml-c14n-20010315), which, as
    discussed earlier in this email, does not make any assumptions regarding
    whitespace belonging to
    elements in the xml being canonicalized and hence treats all such whitespace
    as significant. There
    is no extensibility mechanism defined by XMLDSIG for introducing an XSL
    transform to preprocess the
    ds:SignedInfo element.
    
    Because the ds:CanonicalizationMethod algorithm does not eliminate trivial
    whitespace, ds:SignedInfo
    is sensitive to changes in whitespace, even if the ebXML message in which it
    is embedded is robust.  
    
    The solution to this latter problem is to require MSHs to apply the XSL
    transform to ds:SignedInfo
    elements BEFORE signing and BEFORE verifying (that is, before the XMLDSIG
    implementation gets the
    envelope).  The result is that the signing MSH always creates a
    ds:SignedInfo element that 'fits on
    one line with no trivial whitespace'.  More precisely, the signing MSH must
    always create
    ds:SignedInfo elements that do not contain trivial whitespace anywhere in
    their subtree.  Trivial
    whitespace is defined as any whitespace that would be stripped by applying
    the XSL transform:
    
        <Transform Algorithm="http://www.w3.org/TR/1999/REC-xslt-19991116">
          <xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
            <xsl:strip-space elements='*'/>        <!-- Strip whitespace. -->
            <xsl:template match='node()|@*'>       <!-- The identity transform.
    -->
              <xsl:copy> <xsl:apply-templates select='@*'/>
    <xsl:apply-templates/> </xsl:copy>
            </xsl:template>
          </xsl:stylesheet>
        </Transform>
    
    (the same one as before).
    
    Using the example above, the signing MSH must generate this:
    
      <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
        <ds:SignedInfo><ds:CanonicalizationMethod ...><ds:SignatureMethod
    ...><ds:Reference URI="">...<ds:/SignedInfo>
        <ds:SignatureValue>
     
    asgBjrgjg7u6+Nxwqa1GTKY3AkvORTygCmoXDMIGveiUkmNZ2L4DDgbD6FhGVNMvKVfzsKxv
     
    LRhBV2QW1YsOH+Ot8BpB49lcHdmweMIApbXo0Y+uKe4t73YGE7QAuboLaCQQQ+X++MCu6uzC
          YVnA3zHTuZiEz+qABxbFRgQg20g=
        <ds:/SignatureValue>
      <ds:/Signature>
    
    ('...' is obviously used only to keep the example short).
    
    Similarly, the verifying MSH must remove all trivial whitespace (if any
    exist) belonging to
    ds:SignedInfo before the envelope is submitted to the XMLDSIG library for
    verification.  How trivial
    whitespace is removed from ds:SignedInfo is left to the implementation.
    Implementations might
    (among other options):
    
     - Walk the (normalized) DOM structure rooted at ds:SignedInfo and remove
    all text nodes that
       contain only whitespace.
     - Instantiate a JAXP transformer, initialized with the above XSL transform.
    
    By consistently signing over 'flattened' (referring to this process of
    removing trivial whitespace)
    ds:SignedInfo elements and then 'flattening' these again before verifying,
    signatures become robust
    to changes in whitespace.  Even if an intermediary MSH were to pretty print
    the ebXML envelope and
    embedded ds:Signature elements, signatures are not invalidated.
    
    Thanks for your patience.  Comments and feedback greatly appreciated.
    
    Regards,
    Sanjay J. Cherian
    Sterling Commerce
    Irving, TX