Signature numérique XML, canonicalisation et commentaires

Parmi les différentes options de canonicalisation (c14n) disponibles lors de signature de documents XML, nous trouvons la possibilité de prendre en compte ou non les commentaires dans le calcul du hash…

Dans le cas d’une canonicalisation exclusive, les transformations possibles sont :

  • http://www.w3.org/2001/10/xml-exc-c14n#
  • http://www.w3.org/2001/10/xml-exc-c14n#WithComments

Mais y a-t-il une réelle différence dans le hash (donc dans la signature) ?

Un exemple de nœud XML référencé par l’ID « object » que nous voudrions signer :

<Object Id="object"><!--commentaire-->texte</Object>

… et soumettons-le à différentes transformations en vue d’une signature !

  • Canonicalisation exclusive, avec omission des commentaires (référence par Id) :

    Reference maReference = maSignatureFactory.newReference(
                    "#object",
                    maSignatureFactory.newDigestMethod(DigestMethod.SHA1, null),
                    Collections.singletonList(maSignatureFactory.newTransform(CanonicalizationMethod.EXCLUSIVE, (C14NMethodParameterSpec) null)),
                    "http://www.w3.org/2000/09/xmldsig#Object",
                    "data-object");

    2 – Référence par ID sur le noeud object
    4 – Méthode de canonicalisation exclusive avec omission des commentaires (CanonicalizationMethod.EXCLUSIVE)

    Résultat :

    <Reference Id="data-object" Type="http://www.w3.org/2000/09/xmldsig#Object" URI="#object">
    	<Transforms>
    		<Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
    	</Transforms>
    	<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
    	<DigestValue>xVvVl8rEZss+SMzVbGBf+xjXRm4=</DigestValue>
    </Reference>

    1 – Référence par ID sur le noeud object
    3 – Méthode de canonicalisation exclusive avec omission des commentaires (http://www.w3.org/2001/10/xml-exc-c14n#)
    6 – Hash du noeud XML après canonicalisation : xVvVl8rEZss+SMzVbGBf+xjXRm4=

  • Canonicalisation exclusive, avec conservation des commentaires (référence par Id) :

    Reference maReference = maSignatureFactory.newReference(
                    "#object",
                    maSignatureFactory.newDigestMethod(DigestMethod.SHA1, null),
                    Collections.singletonList(maSignatureFactory.newTransform(CanonicalizationMethod.EXCLUSIVE_WITH_COMMENTS, (C14NMethodParameterSpec) null)),
                    "http://www.w3.org/2000/09/xmldsig#Object",
                    "data-object");

    2 – Référence par ID sur le noeud object
    4 – Méthode de canonicalisation exclusive avec conservation des commentaires (CanonicalizationMethod.EXCLUSIVE_WITH_COMMENTS)

    Résultat :

    <Reference Id="data-object" Type="http://www.w3.org/2000/09/xmldsig#Object" URI="#object">
    	<Transforms>
    		<Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#WithComments"/>
    	</Transforms>
    	<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
    	<DigestValue>xVvVl8rEZss+SMzVbGBf+xjXRm4=</DigestValue>
    </Reference>

    1 – Référence par ID sur le noeud object
    3 – Méthode de canonicalisation exclusive avec conservation des commentaires (http://www.w3.org/2001/10/xml-exc-c14n#WithComments)
    6 – Hash du noeud XML après canonicalisation : xVvVl8rEZss+SMzVbGBf+xjXRm4=

Mais comment est-ce possible ? Dans le premier cas, nous indiquons explicitement une canonicalisation avec omission des commentaires et obtenons le hash : xVvVl8rEZss+SMzVbGBf+xjXRm4=
Puis indiquons une canonicalisation avec conservation des commentaires et obtenons le même hash !

Explications :

Ce comportement vient de petites spécificités de nos amis du W3C… : http://www.w3.org/TR/xmldsig-core/#sec-ReferenceProcessingModel :

When a fragment is not preceded by a URI in the URI-Reference, XML Signature applications MUST support the null URI and shortname XPointer [XPointer-Framework]. We RECOMMEND support for the same-document XPointers ‘#xpointer(/)’ and ‘#xpointer(id(‘ID’))’ if the application also intends to support any canonicalization that preserves comments. (Otherwise URI= »#foo » will automatically remove comments before the canonicalization can even be invoked due to the processing defined in Same-Document URI-References (section 4.3.3.3).) All other support for XPointers is OPTIONAL, especially all support for shortname and other XPointers in external resources since the application may not have control over how the fragment is generated (leading to interoperability problems and validation failures).

Les commentaires seraient ainsi enlevés avant même le processus de canonicalisation de part la méthode de sélection du nœud cible (par référence directe à l’Id), cette lecture est confirmée par un des paragraphes suivants :

URI= »#chapter1″
Identifies a node-set containing the element with ID attribute value ‘chapter1’ of the XML resource containing the signature. XML Signature (and its applications) modify this node-set to include the element plus all descendants including namespaces and attributes — but not comments.

Ainsi, nous devrions pouvoir nous en sortir avec une référence par XPointer sur un Id plutôt qu’une référence directe sur un Id…

  • Canonicalisation exclusive, avec omission des commentaires (référence par XPointer sur Id)) :

    Reference maReference = maSignatureFactory.newReference(
                    "#xpointer(id('object'))",
                    maSignatureFactory.newDigestMethod(DigestMethod.SHA1, null),
                    Collections.singletonList(maSignatureFactory.newTransform(CanonicalizationMethod.EXCLUSIVE, (C14NMethodParameterSpec) null)),
                    "http://www.w3.org/2000/09/xmldsig#Object",
                    "data-object");

    2 – Référence par XPointer sur ID sur le noeud object
    4 – Méthode de canonicalisation exclusive avec omission des commentaires (CanonicalizationMethod.EXCLUSIVE)

    Résultat :

    <Reference Id="data-object" Type="http://www.w3.org/2000/09/xmldsig#Object" URI="#xpointer(id('object'))">
    	<Transforms>
    		<Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
    	</Transforms>
    	<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
    	<DigestValue>xVvVl8rEZss+SMzVbGBf+xjXRm4=</DigestValue>
    </Reference>

    1 – Référence par XPointer ID sur le noeud object
    3 – Méthode de canonicalisation exclusive avec omission des commentaires (http://www.w3.org/2001/10/xml-exc-c14n#)
    6 – Hash du noeud XML après canonicalisation : xVvVl8rEZss+SMzVbGBf+xjXRm4= (le même que précédemment, heureusement ;))

  • Canonicalisation exclusive, avec conservation des commentaires (référence par XPointer sur Id) :

    Reference maReference = maSignatureFactory.newReference(
                   "#xpointer(id('object'))",
                    maSignatureFactory.newDigestMethod(DigestMethod.SHA1, null),
                    Collections.singletonList(maSignatureFactory.newTransform(CanonicalizationMethod.EXCLUSIVE_WITH_COMMENTS, (C14NMethodParameterSpec) null)),
                    "http://www.w3.org/2000/09/xmldsig#Object",
                    "data-object");

    2 – Référence par XPointer sur ID sur le noeud object
    4 – Méthode de canonicalisation exclusive avec conservation des commentaires (CanonicalizationMethod.EXCLUSIVE_WITH_COMMENTS)

    Résultat :

    <Reference Id="data-object" Type="http://www.w3.org/2000/09/xmldsig#Object" URI="#xpointer(id('object'))">
    	<Transforms>
    		<Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#WithComments"/>
    	</Transforms>
    	<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
    	<DigestValue>vHnUzn+afpzilGODV/4utR5xIlQ=</DigestValue>
    </Reference>

    1 – Référence par XPointer sur ID sur le noeud object
    3 – Méthode de canonicalisation exclusive avec conservation des commentaires (http://www.w3.org/2001/10/xml-exc-c14n#WithComments)
    6 – Hash du noeud XML après canonicalisation : vHnUzn+afpzilGODV/4utR5xIlQ=

Cette fois-ci le « bon » hash !!!

Conclusions et remarques :

Dans tous les cas précédents, les hashs et signatures engendrés seront heureusement corrects, mais certaines incompréhensions peuvent découler de l’utilisation des références par Id lors de canonicalisation avec conservation des commentaires… Un document dans lequel nous aurions modifié les commentaires de manière insultante ou publicitaire garderait une signature correcte malgré l’utilisation explicite de canonicalisation avec conservation des commentaires.

L’utilisation de référence par XPointer explicite, dont le support est déjà recommandé par le W3C pour les signatures XMLDSIG, est donc un bon choix.
Malheureusement ce type de référence n’est pas forcément encore supporté par tous les logiciels de signature ou de vérification de signature.

Références :