Partager via


Classe System.Security.Cryptography.Xml.SignedXml

Cet article vous offre des remarques complémentaires à la documentation de référence pour cette API.

La SignedXml classe est l’implémentation .NET de la syntaxe et du traitement de signature XML W3C (World Wide Web Consortium), également appelée XMLDSIG (signature numérique XML). XMLDSIG est un moyen basé sur des normes et interopérable de signer et de vérifier tout ou partie d’un document XML ou d’autres données adressables à partir d’un URI (Uniform Resource Identifier).

Utilisez la SignedXml classe chaque fois que vous devez partager des données XML signées entre des applications ou des organisations de manière standard. Toutes les données signées à l’aide de cette classe peuvent être vérifiées par toute implémentation conforme de la spécification W3C pour XMLDSIG.

La SignedXml classe vous permet de créer les trois types de signatures numériques XML suivantes :

Signature Type Description
Signature enveloppée La signature est contenue dans l’élément XML en cours de signature.
Signature enveloping Le code XML signé est contenu dans l’élément <Signature> .
Signature détachée interne La signature et le code XML signé se trouvent dans le même document, mais aucun élément ne contient l’autre.

Il existe également un quatrième type de signature appelé signature détachée externe, c’est-à-dire lorsque les données et la signature se trouvent dans des documents XML distincts. Les signatures détachées externes ne sont pas prises en charge par la SignedXml classe.

Structure d’une signature XML

XMLDSIG crée un <Signature> élément, qui contient une signature numérique d’un document XML ou d’autres données adressables à partir d’un URI. L’élément <Signature> peut éventuellement contenir des informations sur l’emplacement où trouver une clé qui vérifie la signature et l’algorithme de chiffrement utilisé pour la signature. La structure de base est la suivante :

<Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
    <SignedInfo>
      <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
      <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
      <Reference URI="">
        <Transforms>
          <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
        </Transforms>
        <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
        <DigestValue>Base64EncodedValue==</DigestValue>
      </Reference>
    </SignedInfo>
    <SignatureValue>AnotherBase64EncodedValue===</SignatureValue>
</Signature>

Les principales parties de cette structure sont les suivantes :

  • L’élément <CanonicalizationMethod>

    Spécifie les règles de réécriture de l’élément Signature à partir de XML/text en octets pour la validation de signature. La valeur par défaut dans .NET est http://www.w3.org/TR/2001/REC-xml-c14n-20010315, qui identifie un algorithme fiable. Cet élément est représenté par la SignedInfo.CanonicalizationMethod propriété.

  • L’élément <SignatureMethod>

    Spécifie l’algorithme utilisé pour la génération et la validation de signature, qui a été appliqué à l’élément <Signature> pour produire la valeur dans <SignatureValue>. Dans l’exemple précédent, la valeur http://www.w3.org/2000/09/xmldsig#rsa-sha1 identifie une signature SHA-1 RSA PKCS1. En raison de problèmes de collision avec SHA-1, Microsoft recommande un modèle de sécurité basé sur SHA-256 ou mieux. Cet élément est représenté par la SignatureMethod propriété.

  • L’élément <SignatureValue>

    Spécifie la signature de chiffrement de l’élément <Signature> . Si cette signature ne vérifie pas, une partie du <Signature> bloc a été falsifiée et le document est considéré comme non valide. Tant que la <CanonicalizationMethod> valeur est fiable, cette valeur est hautement résistante à la falsification. Cet élément est représenté par la SignatureValue propriété.

  • Attribut URI de l’élément <Reference>

    Spécifie un objet de données à l’aide d’une référence d’URI. Cet attribut est représenté par la Reference.Uri propriété.

    • Ne pas spécifier l’attribut URI , autrement dit, définir la Reference.Uri propriété nullsur , signifie que l’application de réception est censée connaître l’identité de l’objet. Dans la plupart des cas, un null URI entraîne la levée d’une exception. N’utilisez pas d’URI null , sauf si votre application interopérait avec un protocole qui l’exige.

    • La définition de l’attribut URI sur une chaîne vide indique que l’élément racine du document est signé, une forme de signature enveloppe.

    • Si la valeur de l’attribut URI commence par #, la valeur doit être résolue en un élément du document actif. Ce formulaire peut être utilisé avec n’importe quel type de signature pris en charge (signature enveloppée, signature enveloppante ou signature détachée interne).

    • Tout autre élément est considéré comme une signature détachée de ressource externe et n’est pas pris en charge par la SignedXml classe.

  • L’élément <Transforms>

    Contient une liste ordonnée d’éléments <Transform> qui décrivent comment le signataire a obtenu l’objet de données qui a été digesté. Un algorithme de transformation est similaire à la méthode de canonisation, mais au lieu de réécrire l’élément <Signature> , il réécrit le contenu identifié par l’attribut URI de l’élément <Reference> . L’élément <Transforms> est représenté par la TransformChain classe.

    • Chaque algorithme de transformation est défini comme prenant xml (un jeu de nœuds XPath) ou des octets comme entrée. Si le format des données actuelles diffère des exigences d’entrée de transformation, les règles de conversion sont appliquées.

    • Chaque algorithme de transformation est défini comme produisant du code XML ou des octets comme sortie.

    • Si la sortie du dernier algorithme de transformation n’est pas définie en octets (ou si aucune transformation n’a été spécifiée), la méthode de canonisation est utilisée comme transformation implicite (même si un autre algorithme a été spécifié dans l’élément <CanonicalizationMethod> ).

    • Une valeur de l’algorithme de http://www.w3.org/2000/09/xmldsig#enveloped-signature transformation encode une règle interprétée comme supprimant l’élément <Signature> du document. Dans le cas contraire, un vérificateur d’une signature enveloppée permet de condenser le document, y compris la signature, mais le signataire aurait digesté le document avant l’application de la signature, entraînant des réponses différentes.

  • L’élément <DigestMethod>

    Identifie la méthode digest (hachage de chiffrement) à appliquer sur le contenu transformé identifié par l’attribut URI de l’élément <Reference> . Ceci est représenté par la Reference.DigestMethod propriété.

Choix d’une méthode de canonisation

À moins d’interagir avec une spécification qui nécessite l’utilisation d’une valeur différente, nous vous recommandons d’utiliser la méthode de canonisation .NET par défaut, qui est l’algorithme XML-C14N 1.0, dont la valeur est http://www.w3.org/TR/2001/REC-xml-c14n-20010315. L’algorithme XML-C14N 1.0 doit être pris en charge par toutes les implémentations de XMLDSIG, en particulier lorsqu’il s’agit d’une transformation finale implicite à appliquer.

Il existe des versions d’algorithmes de canonisation qui prennent en charge la conservation des commentaires. Les méthodes de canonisation préservant les commentaires ne sont pas recommandées, car elles violent le principe de « signe vu ». Autrement dit, les commentaires d’un <Signature> élément ne modifient pas la logique de traitement pour la façon dont la signature est effectuée, simplement ce que la valeur de signature est. Lorsqu’ils sont combinés avec un algorithme de signature faible, ce qui permet aux commentaires d’être inclus donne à un attaquant une liberté inutile de forcer une collision de hachage, ce qui rend un document falsifié légitime. Dans .NET Framework, seuls les canoniques intégrés sont pris en charge par défaut. Pour prendre en charge des canoniques supplémentaires ou personnalisés, consultez la SafeCanonicalizationMethods propriété. Si le document utilise une méthode de canonisation qui n’est pas dans la collection représentée par la SafeCanonicalizationMethods propriété, la CheckSignature méthode retourne false.

Remarque

Une application extrêmement défensive peut supprimer toutes les valeurs qu’elle ne s’attend pas à ce que les signataires utilisent de la SafeCanonicalizationMethods collection.

Les valeurs de référence ne peuvent-elles pas être falsifiées ?

Oui, les <Reference> valeurs ne sont pas falsifiées. .NET vérifie le <SignatureValue> calcul avant de traiter l’une <Reference> des valeurs et leurs transformations associées, et abandonne tôt pour éviter les instructions de traitement potentiellement malveillantes.

Choisir les éléments à signer

Nous vous recommandons d’utiliser la valeur « » pour l’attribut URI (ou de définir la Uri propriété sur une chaîne vide), si possible. Cela signifie que l’ensemble du document est pris en compte pour le calcul de synthèse, ce qui signifie que l’ensemble du document est protégé contre la falsification.

Il est très courant de voir URI les valeurs sous la forme d’ancres telles que #foo, faisant référence à un élément dont l’attribut ID est « foo ». Malheureusement, il est facile d’être falsifié car cela inclut uniquement le contenu de l’élément cible, et non le contexte. L’abus de cette distinction est connu sous le nom d’habillage de signature XML (XSW).

Si votre application considère que les commentaires sont sémantiques (ce qui n’est pas courant lorsque vous traitez avec XML), vous devez utiliser « #xpointer(/) » au lieu de « » et « #xpointer(id('foo')) » au lieu de « #foo ». Les versions #xpointer sont interprétées comme incluant des commentaires, tandis que les formulaires de nom court excluent les commentaires.

Si vous devez accepter des documents qui ne sont que partiellement protégés et que vous souhaitez vous assurer que vous lisez le même contenu que celui protégé par la signature, utilisez la GetIdElement méthode.

Considérations relatives à la sécurité relatives à l’élément KeyInfo

Les données de l’élément facultatif <KeyInfo> (autrement dit, la KeyInfo propriété), qui contient une clé pour valider la signature, ne doivent pas être approuvées.

En particulier, lorsque la KeyInfo valeur représente une clé publique RSA, DSA ou ECDSA nue, le document a pu être falsifié, malgré la CheckSignature méthode signalant que la signature est valide. Cela peut se produire, car l’entité qui effectue la falsification doit simplement générer une nouvelle clé et signer à nouveau le document falsifié avec cette nouvelle clé. Par conséquent, sauf si votre application vérifie que la clé publique est une valeur attendue, le document doit être traité comme s’il a été falsifié. Cela nécessite que votre application examine la clé publique incorporée dans le document et la vérifie sur une liste de valeurs connues pour le contexte du document. Par exemple, si le document peut être compris comme émis par un utilisateur connu, vous case activée la clé par rapport à une liste de clés connues utilisées par cet utilisateur.

Vous pouvez également vérifier la clé après avoir traité le document à l’aide de la CheckSignatureReturningKey méthode, au lieu d’utiliser la CheckSignature méthode. Toutefois, pour une sécurité optimale, vous devez vérifier la clé au préalable.

Vous pouvez également essayer les clés publiques inscrites de l’utilisateur plutôt que de lire ce qui se trouve dans l’élément <KeyInfo> .

Considérations relatives à la sécurité relatives à l’élément X509Data

L’élément facultatif <X509Data> est un enfant de l’élément <KeyInfo> et contient un ou plusieurs certificats ou identificateurs X509 pour les certificats X509. Les données de l’élément <X509Data> ne doivent pas non plus être intrinsèquement approuvées.

Lors de la vérification d’un document avec l’élément incorporé <X509Data> , .NET vérifie uniquement que les données sont résolues sur un certificat X509 dont la clé publique peut être utilisée avec succès pour valider la signature du document. Contrairement à l’appel de la CheckSignature méthode avec le verifySignatureOnly paramètre défini falsesur , aucune case activée de révocation n’est effectuée, aucune approbation de chaîne n’est case activée ed et aucune expiration n’est vérifiée. Même si votre application extrait le certificat lui-même et le transmet à la CheckSignature méthode avec le verifySignatureOnly paramètre défini falsesur , qui n’est toujours pas suffisant pour empêcher la falsification de document. Le certificat doit toujours être vérifié comme approprié pour le document signé.

L’utilisation d’un certificat de signature incorporé peut fournir des stratégies de rotation de clés utiles, que ce soit dans la <X509Data> section ou dans le contenu du document. Lorsque vous utilisez cette approche, une application doit extraire le certificat manuellement et effectuer une validation similaire à :

  • Le certificat a été émis directement ou via une chaîne par une autorité de certification dont le certificat public est incorporé dans l’application.

    L’utilisation de la liste d’approbation fournie par le système d’exploitation sans case activée supplémentaires, comme un nom d’objet connu, n’est pas suffisante pour empêcher la falsification.SignedXml

  • Le certificat est vérifié qu’il n’a pas été expiré au moment de la signature de document (ou « maintenant » pour le traitement de documents en quasi temps réel).

  • Pour les certificats de longue durée émis par une autorité de certification qui prend en charge la révocation, vérifiez que le certificat n’a pas été révoqué.

  • L’objet du certificat est vérifié comme approprié pour le document actif.

Choix de l’algorithme de transformation

Si vous interagissez avec une spécification qui a dicté des valeurs spécifiques (telles que XrML), vous devez suivre la spécification. Si vous avez une signature enveloppe (par exemple, lors de la signature de l’ensemble du document), vous devez utiliser http://www.w3.org/2000/09/xmldsig#enveloped-signature (représentée par la XmlDsigEnvelopedSignatureTransform classe). Vous pouvez également spécifier la transformation XML-C14N implicite, mais elle n’est pas nécessaire. Pour une signature enveloppante ou détachée, aucune transformation n’est requise. La transformation XML-C14N implicite prend en charge tout.

Avec la sécurité mise à jour par le Bulletin de sécurité Microsoft MS16-035, .NET a restreint les transformations qui peuvent être utilisées dans la vérification de document par défaut, avec des transformations non approuvées provoquant toujours un CheckSignature retour false. En particulier, les transformations qui nécessitent une entrée supplémentaire (spécifiée en tant qu’éléments enfants dans le XML) ne sont plus autorisées en raison de leur sensibilité à l’abus par des utilisateurs malveillants. Le W3C conseille d’éviter les transformations XPath et XSLT, qui sont les deux transformations principales affectées par ces restrictions.

Le problème avec les références externes

Si une application ne vérifie pas que les références externes semblent appropriées pour le contexte actuel, elles peuvent être abusées de manière à fournir de nombreuses vulnérabilités de sécurité (y compris déni de service, déni de service distribué Réflexions ion de déni de service, divulgation d’informations, contournement de signature et exécution de code distant). Même si une application devait valider l’URI de référence externe, il y aurait un problème de chargement de la ressource deux fois : une fois lorsque votre application l’a lue et une fois lors SignedXml de sa lecture. Étant donné qu’il n’existe aucune garantie que les étapes de lecture et de vérification des documents de l’application ont le même contenu, la signature ne fournit pas de fiabilité.

Étant donné les risques liés aux références externes, SignedXml lève une exception lorsqu’une référence externe est rencontrée. Pour plus d’informations sur ce problème, consultez Ko article 3148821.