L’infrastructure de signature numérique des conventions open packaging

 

David Meltzer et Andrey Shur
Microsoft Corporation

Septembre 2006

S’applique à :
   Infrastructure de signature numérique OPC
   W3C XML Digital Signature standard
   Microsoft .NET 3.0 Framework

Résumé : Présente OPC Digital Signing Framework, fournit une vue d’ensemble des composants du package et des services de prise en charge, ainsi que des exemples de stratégie de signature et de son implémentation. (12 pages imprimées)

Contenu

Introduction
Composants de l’infrastructure de signature numérique OPC
   The XML Digital Signature Standard
   Représentation des signatures numériques dans les packages
   Signature de parties et de relations
Prise en charge de la programmation pour les signatures de package
   Parties et relations de package de signature
   Vérification des certificats et des signatures
Stratégie de signature d’application
   Documents XPS
   Prise en charge de la programmation pour les signatures XPS
Références

Introduction

Le modèle d’empaquetage spécifié par les conventions OPC (Open Packaging Conventions) décrit les packages, les parties et les relations. Les packages contiennent des parties qui contiennent du contenu et des ressources. Les relations sont définies pour connecter le package à des parties et pour connecter les différentes parties du package.

Cet article présente OPC Digital Signing Framework, en fournissant une vue d’ensemble des composants de package et des services de prise en charge, ainsi que des exemples de stratégie de signature et de son implémentation.

L’infrastructure de signature comprend une infrastructure de représentation des signatures numériques et les services de création et de validation des signatures. L’infrastructure de signature permet d’appliquer la norme de signature numérique XML W3C aux parties et aux relations de package.

À l’aide de l’infrastructure de signature, les propriétaires de formats basés sur des packages définissent et implémentent des « stratégies de signature » spécifiques à leurs formats. Les stratégies spécifient comment signer et valider le contenu intégral de formats particuliers, et incarnent la façon dont les signatures sont utilisées pour différents flux de travail. En fait, pour un format unique, plusieurs stratégies peuvent être définies pour une utilisation à différentes étapes du cycle de vie d’un document.

La stratégie de signature d’un format basé sur un package est exprimée en termes de parties et de relations de signature, et éventuellement d’autres caractéristiques du document (telles que la validation du périphérique d’affichage prévu, la profondeur de couleur ou la version de l’application). Une stratégie de signature spécifie les composants de document à signer et ceux à laisser non signés, le cas échéant. Par exemple, une stratégie de signature peut être implémentée pour permettre l’ajout de nouvelles parties et relations à un package, ou une stratégie peut entraîner l’invalidation d’une signature si de nouvelles parties ou signatures sont ajoutées à un package.

Cet article suppose que vous êtes familiarisé avec la spécification Open Packaging Conventions et la syntaxe et le traitement de la signature XML de la recommandation W3C.

Composants de l’infrastructure de signature numérique OPC

The XML Digital Signature Standard

L’infrastructure de signature pour les packages utilise la norme de signature numérique XML, telle que définie dans la recommandation du W3C , syntaxe et traitement des signatures XML. Cette recommandation spécifie la syntaxe XML et les règles de traitement pour la production et le stockage des signatures numériques.

La norme définit un type d’élément de signature XML, un schéma et des exigences de conformité pour la signature et la validation de tout type de ressource numérique. Le schéma définit également des éléments pour référencer des ressources et spécifier des algorithmes liés à la signature.

Fonctionnalités des signatures numériques

Une signature numérique peut être utilisée pour déterminer si le contenu signé a changé depuis sa signature. La signature contient un manifeste de contenu qui est haché selon un algorithme bien connu et stocké dans la signature lors de sa création. Pour déterminer si le contenu a changé, un hachage du contenu signé est recréé et comparé au hachage stocké dans la signature.

Une signature numérique peut également être utilisée pour identifier le signataire du contenu. L’identité du signataire est représentée par un certificat associé à la signature. Le certificat peut être incorporé dans la signature ou disponible ailleurs.

Une signature numérique ne « verrouille » pas un document et ne provoque pas son chiffrement (bien qu’il soit déjà chiffré). Le contenu du document reste inchangé après avoir été signé. Les signatures numériques n’empêchent pas l’affichage du contenu signé par des consommateurs involontaires.

Représentation des signatures numériques dans les packages

Les applications incorporent des signatures numériques dans un package à l’aide d’une configuration spécifiée de parties et de relations.

L’infrastructure de signature utilise des éléments et des attributs de l’espace de noms d’empaquetage lorsque la norme XML Digital Signature le permet. Les éléments de signature définis dans l’espace de noms d’empaquetage prennent en charge des fonctionnalités spécifiques au package qui augmentent la norme sans la contredire. Pour obtenir un résumé des ajouts, consultez la section « Modifications apportées à la spécification de signature numérique XML » de la spécification OPC.

Les composants de package définis pour l’infrastructure de signature sont la partie Origine, la partie Signature XML et la partie Certificat. Chacun a un type de contenu bien défini. Les types de relation bien définis sont utilisés pour connecter des parties de signature dans un package, comme spécifié dans l’Annexe H, « Espaces de noms et types de contenu standard », de la spécification OPC.

Composant d’origine de la signature numérique

La partie Origine de la signature numérique est le point de départ de la navigation dans les signatures d’un package. La partie Origine de la signature numérique est ciblée à partir de la racine du package à l’aide de la relation Digital Signature Origin . Plusieurs parties signature peuvent être ciblées à partir de la partie Origine. S’il n’y a pas de signatures dans le package, la partie Origine n’est pas présente.

Composant signature XML signature numérique

Les composants Signature XML signature numérique contiennent le balisage défini dans la norme W3C Digital Signature ainsi que dans l’espace de noms d’empaquetage. Les parties sont ciblées à partir du xml de la partie Origine de la signature numérique avec la relation Signature numérique .

Composant certificat de signature numérique

Le certificat X.509 requis pour identifier le signataire, s’il est placé dans le package, peut être incorporé dans la partie Signature XML ou stocké dans un composant Certificat distinct. Le composant Certificat facultatif est ciblé à partir du composant Signature XML avec la relation Certificat de signature numérique . La partie Certificat peut être partagée entre plusieurs parties Signature.

Composants de signature personnalisés

Les parties de signature personnalisées (spécifiques à l’application) sont autorisées, mais pas gérées, par l’infrastructure de signature. Une partie de signature qui contient une forme de signature autre qu’une signature XML doit être identifiée par un type de contenu personnalisé. En outre, une relation avec un type de relation personnalisé doit être utilisée pour cibler la partie à partir de la partie Origine de la signature numérique.

Signature de parties et de relations

La norme XML Digital Signature permet la signature de ressources adressables, qui, pour un package, sont des parties. L’infrastructure de signature active la signature des parties. Les relations d’un package, stockées dans une partie de relations, peuvent être signées à la fois, ou un sous-ensemble de relations peut être spécifié pour la signature.

Le type de contenu d’un composant est signé, ainsi que le contenu du composant, pour garantir qu’une partie d’un package validement signé sera utilisée ou rendue comme prévu. Étant donné que le type de contenu n’est pas une ressource adressable, une approche spécifique au package est adoptée pour signer la valeur du type de contenu. Lorsque le package est signé, le type de contenu de chaque partie signée est stocké dans le composant de requête de l’URI faisant référence à la partie signée. Lorsque le package est consommé, OPC Digital Signing Framework utilise la valeur de type de contenu pour s’assurer que le type de contenu du composant n’a pas changé depuis la signature du composant.

Lorsque la partie relations est signée dans son ensemble, toutes les relations définies dans ce composant sont signées. Pour prendre en charge les stratégies de signature qui permettent de modifier certains contenus d’un package sans invalider la signature, l’infrastructure de signature fournit un mécanisme pour signer les relations spécifiées. Pour signer des relations spécifiées, l’infrastructure de signature utilise une transformation spéciale, la transformation de relations (voir Algorithmes de transformation).

La transformation de relations crée une partie de relations contenant uniquement l’ensemble de relations spécifié. La partie relations obtenues est utilisée pour la signature et pendant la validation de la signature.

Prise en charge de la programmation pour les signatures de package

Pour signer et valider des signatures, les applications peuvent utiliser les classes .NET 3.0 PackageDigitalSignatureManager. Les classes spécifiques au package, définies dans l’espace de noms System.IO.Packaging , s’appuient sur les classes de signature numérique de Microsoft .NET 3.0 Framework définies dans l’espace de nomsSystem.Security.Cryptography.Xml .

La classe PackageDigitalSignatureManager est utilisée pour créer et valider des signatures et placer l’infrastructure de signature dans un package. La signature est représentée par un objet basé sur la classe PackageDigitalSignature .

Parties et relations de package de signature

Une application définit une liste de parties et de relations à signer en fonction de sa stratégie de signature. L’application appelle ensuite la méthode PackageDigitalSignatureManager.Sign() pour créer la signature et ajouter l’infrastructure de signature au package.

L’exemple de code ci-dessous illustre la signature de toutes les parties du package à l’exception des parties de relations, la signature de toutes les relations existantes provenant de la racine du package et l’incorporation du certificat utilisé pour la signature dans le composant Signature XML. L’exemple de code suppose qu’aucune signature n’existe dans le package au début et qu’une seule signature est appliquée avant la vérification.

Début du processus de signature

Pour commencer à utiliser des signatures dans le package, commencez par créer un PackageDigitalSignatureManager, comme indiqué ci-dessous.

    // Open the package.
    Package package = Package.Open(filename);

    // Create the PackageDigitalSignatureManager
      PackageDigitalSignatureManager dsm =
        new PackageDigitalSignatureManager(package);

Options d’incorporation de certificats

Un certificat peut être représenté sous la forme d’une chaîne incorporée dans la signature elle-même, en tant que partie distincte du package ou en tant que ressource en dehors du package. Si le certificat doit être placé dans le package, une application spécifie comment le certificat sera conservé à l’aide des options d’incorporation de la propriété PackageDigitalSignature.CertificateOption . Après avoir créé la classe PackageDigitalSignatureManager , les options d’incorporation du certificat sont définies, comme indiqué dans l’exemple de code ci-dessous.

    //Specify that the certificate is embedded in the signature held
    //in the XML Signature part.

    //Certificate embedding options include:
    // InSignaturePart – Certificate is embedded in the signature.
    // InCertificatePart – Certificate is embedded in a 
    //                     separate certificate part

    dsm.CertificateOption =
        CertificateEmbeddingOption.InSignaturePart;

Liste des parties signées

La liste des parties à signer est spécifiée à l’aide des URI qui s’adressent aux parties. Dans cet exemple, toutes les parties du package seront signées, à l’exception des parties de relations, qui sont filtrées à l’aide de la méthode PackUriHelper.IsRelationshipPartUri().

    //Initialize a list to hold the part URIs to sign.

    System.Collections.Generic.List<Uri> partsToSign =
        new System.Collections.Generic.List<Uri>();

    //Add each part to the list, except relationships parts.
    foreach (PackagePart packagePart in package.GetParts())
    {
        if (!PackUriHelper.IsRelationshipPartUri(packagePart.Uri))
      partsToSign.Add(packagePart.Uri);
  }

Liste des relations signées

Les relations individuelles sont signées à l’aide de la transformation des relations. La signature des relations de cette façon permet d’ajouter de nouvelles relations au package sans invalider la signature.

Les relations sont sélectionnées pour la signature en créant une liste d’objets PackageRelationshipSelector qui seront utilisés au moment de la signature. Les objets PackageRelationshipSelector peuvent être créés en tant que groupe par type de relation (comme défini dans la section « Espaces de noms et types de contenu standard » des conventions open packaging), ou créés individuellement en spécifiant l’ID de relation, comme dans l’exemple ci-dessous.

     //Create list of selectors for the list of relationships

     List<PackageRelationshipSelector> relationshipSelectors = 
          new List<PackageRelationshipSelector>();

     //Create one selector for each package-level relationship, based on id

  foreach (PackageRelationship relationship in package.GetRelationships())
            {
                relationshipSelectors.Add(new
                    PackageRelationshipSelector(relationship.sourceUri, 
                    PackageRelationshipSelectorType.Id, relationship.Id));
            }

Lors de la création d’un PackageRelationshipSelector avec PackageRelationshipSelectorType.Id, la seule relation avec l’ID unique spécifié est sélectionnée pour la signature. Lors de la création d’un sélecteur avec PackageRelationshipSelectorType.Type, toutes les relations avec le type spécifié sont sélectionnées pour la signature. Si des relations du même type sont ajoutées ultérieurement à un package, la signature est invalidée.

Création de l’objet Certificate

Avant la signature, un certificat X.509 valide est obtenu en instanciant un objet de type System.Security.Cryptography.X509Certificates.X509Certificate2. Cet objet est passé à la méthode PackageDigitalSignatureManager.Sign() au moment de la signature. Pour plus d’informations sur la création d’objets de certificat, consultez l’espace de noms System.Security.Cryptography.X509Certificates .

Application de la signature

Après avoir créé la liste des parties et des relations à signer et obtenu l’objet de certificat, une application appelle la méthode PackageDigitalSignatureManager.Sign().

     //Sign package using components created above

     PackageDigitalSignature signature = dsm.Sign(partsToSign, 
          x509Certificate, relationshipSelectors);

     //After signing, close the package.
     //The signature will be persisted in the package.
     package.Close();

Lorsque la méthode Sign() est appelée, le hachage est généré et stocké dans le manifeste de signature, et la partie signature est créée. Si l’infrastructure de signature existe déjà dans le package, la nouvelle partie de signature est ajoutée (si autorisée). Si l’infrastructure n’existe pas encore dans le package, la méthode Sign() crée l’infrastructure et la place dans le package.

Vérification des certificats et des signatures

Les applications peuvent vérifier un certificat ou une signature. Avant de vérifier la signature, le certificat doit être vérifié. L’objet qui représente la signature dans le package, PackageDigitalSignature, a une propriété « Signer » qui retourne le certificat utilisé pour créer cette signature, s’il se trouve dans le package. Si le certificat n’est pas incorporé dans le package, l’application obtient le certificat à partir d’un emplacement connu de l’application.

La méthode PackageDigitalSignatureManager.VerifyCertificate() permet de valider le certificat obtenu, de vérifier la structure du certificat, la date d’expiration et la chaîne status. Pour plus d’informations sur les status de chaîne, consultez Énumération X509ChainStatusFlag dans la bibliothèque de classes .NET Framework.

Les développeurs d’applications peuvent utiliser les status de certificat pour prendre en charge leurs stratégies de signature. Par exemple, une application peut spécifier que seuls les certificats émis après certaines dates sont acceptables.

La méthode PackageDigitalSignatureManager.VerifySignatures() est utilisée pour valider toutes les signatures dans le package. Cette méthode valide uniquement les signatures, pas les certificats associés aux signatures.

L’exemple de code ci-dessous peut être utilisé pour valider le certificat et la signature placés dans le package dans les exemples de signature. L’exemple de code suppose qu’aucune signature supplémentaire n’a été ajoutée au package.

    // Open the package.

    Package package = Package.Open(filename);

    // Create the PackageDigitalSignatureManager

    PackageDigitalSignatureManager dsm =
        new PackageDigitalSignatureManager(package);

    // Verify the collection of certificates in the package (one, in this case)

        foreach(PackageDigitalSignature signature in pdsm.Signatures)
        {
        if(PackageDigitalSignatureManager.VerifyCertificate(signature.Signer)
            != X509ChainStatusFlags.NoError)
              {
                // Application-specific code for error handling 
                // or certificate validation 
              }
        }
 
   // For this example, if all certificates are valid,
   // verify all signatures in the package.
 
    VerifyResult vResult = dsm.VerifySignatures(false);
    Console.WriteLine("Result " + vResult.ToString());

    // Close the package.

    package.Close();

Stratégie de signature d’application

Les applications qui utilisent des formats basés sur des packages définissent leurs propres stratégies dans le cadre de l’infrastructure de signature. La stratégie est déterminée par les types d’éléments et les exigences de flux de travail du format. Dans cette section, la stratégie de signature est décrite pour un format basé sur un package Microsoft : le format document XPS.

Documents XPS

Le format de document XPS est basé sur les conventions d’emballage open, comme spécifié dans la spécification de papier XML. La spécification de papier XML définit la stratégie de signature de documents XPS. Dans cette stratégie, il existe des options de signature disponibles pour prendre en charge les fonctionnalités d’application ou le flux de travail.

Stratégie de signature pour les packages de documents XPS

La stratégie de signature des documents XPS décrit l’ensemble des parties et des relations qui doivent être signées pour que le contenu puisse être validé. Dans le cadre de cette stratégie, une application peut créer une signature qui inclut éventuellement une combinaison de parties particulières qui sont associées au contenu, telles que la partie CoreProperties. La signature de ces parties empêche leur modification sans invalider la signature. En outre, les applications peuvent éventuellement signer la partie de relations attachée à la partie Origine de la signature numérique dans la signature, ce qui empêche l’ajout de nouvelles signatures au document sans invalider la signature.

Pour qu’une signature soit valide, la stratégie de signature de document XPS nécessite que certaines parties et relations soient incluses dans la signature. Aucune partie ou relation non reconnue ne peut être signée. Lors de la vérification d’une signature, une application doit confirmer que toutes les parties et relations requises sont signées.

Parties de document XPS à signer

Le tableau suivant contient la liste des parties qui doivent être signées dans tous les documents XPS et les parties qui sont éventuellement signées. Pour les relations, la stratégie de signature XPS spécifie que les relations requises (relations ciblant les parties requises) sont toujours signées à l’aide de la transformation des relations définie par OPC. Si un composant est signé, les relations qui le ciblent doivent également être signées.

Type de pièce Stratégie
Composant FixedDocumentSequence Doit être signé
Composant FixedDocument Doit être signé
Composants DocumentStructure Doit être signé
Composant SignatureDefinitions Doit être signé
Composants FixedPage Doit être signé
Parties de ressources requises (telles que les polices, les images) Doit être signé
Composants StoryFragments Doit être signé
Parties miniatures Doit être signé
Partie CoreProperties Signé éventuellement
Partie Origine de la signature numérique Signé éventuellement
Composant Certificat de signature numérique Signé éventuellement
Composants PrintTicket Signé éventuellement
Composants DiscardControl Signé éventuellement

Pour plus d’informations sur la stratégie de signature XPS, consultez la section « Fonctionnalités du package de documents XPS : Signatures numériques : règles de signature » dans la spécification de papier XML.

Stratégie de signature de compatibilité du balisage

La spécification de papier XML décrit un moyen d’inclure du contenu de remplacement dans un document XPS : compatibilité du balisage. Le contenu de remplacement est placé dans des éléments de l’espace de noms Compatibilité du balisage. Par stratégie, les documents XPS qui ont des éléments et des attributs de compatibilité de balisage ne peuvent pas être signés de manière valide, sauf si l’application de signature reconnaît toutes les alternatives de contenu comme équivalentes. Seuls les documents XPS contenant des éléments et des attributs reconnus peuvent être signés ou validés.

Contre-signatures

Plusieurs signatures peuvent être appliquées au contenu d’un document XPS. Par exemple, le contenu représentant un contrat légal peut nécessiter que plusieurs personnes appliquent leurs signatures, indiquant le contenu signé et l’identité du signataire.

L’ajout d’une nouvelle signature crée toujours une nouvelle relation au sein de la partie relations attachée à la partie Origine de la signature numérique. Pour ajouter de nouvelles signatures à un document XPS sans invalider les signatures existantes, cette partie de relations doit rester non signée (bien qu’un sous-ensemble de relations puisse être signé). Si la partie relations est incluse dans une signature, cette signature sera invalidée par toutes les signatures appliquées ultérieurement.

Validation des signatures XPS

En plus de définir la création de signature, la stratégie de signature XPS spécifie également comment vérifier la validité d’une signature. La stratégie définit les états de validité d’une signature qui incluent des éléments non conformes, rompus, douteux et valides, comme indiqué dans le tableau suivant.

État de la signature Toutes les parties et relations requises sont signées ? La signature inclut uniquement le contenu reconnu ? Le hachage du contenu signé est vérifié ? Le contenu de compatibilité de balisage signé est reconnu ? Le certificat est valide ?
Incomplint Non

YES

n/a

Non

n/a

n/a

n/a

n/a

n/a

n/a

Rompu YES YES Non n/a n/a
Douteuse YES

YES

YES

YES

YES

YES

Non

YES

n/a

Non

Valide YES YES YES YES YES

La visionneuse XPS affiche des signatures XPS douteuses et rompues, ainsi que des signatures XPS valides. Les signatures non conformes ne sont pas énumérées.

Prise en charge de la programmation pour les signatures XPS

Lors de l’utilisation d’un document XPS, les applications peuvent utiliser les méthodes de la classe XpsDigitalSignature . Cette classe est basée sur la classe PackageDigitalSignature et comprend des méthodes qui suivent les algorithmes et les exigences spécifiés dans la spécification de signature numérique XPS. Les méthodes de signature et de validation vérifient que toutes les parties et relations requises d’un document XPS sont signées.

Signature d’un document XPS

La méthode XpsDocument.SignDigitally() est utilisée pour signer un document XPS. Avant d’appeler la méthode, une application doit disposer d’un certificat X.509, qui peut être obtenu à l’aide de l’objet System.Security.Cryptography.X509Certificates.X509Certificate2.

     // Open the XPS Document

     XpsDocument document = new XpsDocument(dstContainer,
          FileAccess.ReadWrite);

     // Obtain the certificate object from a file

     X509Certificate certificate =
          509Certificate.CreateFromCertFile(certFilename);

     // Create the signature and add it to the document using
     // the OPC Signing Framework

     document.SignDigitally(certificate, true, 
          XpsDigSigPartAlteringRestrictions.None);

XpsDigSigPartAlteringRestrictions peut être utilisé pour spécifier des restrictions supplémentaires pour une signature, en fonction de la stratégie de signature. Ce paramètre spécifie s’il faut exclure les parties CoreMetadata et/ou SignatureOrigin de la signature. Les parties exclues peuvent ensuite être modifiées ultérieurement sans invalider la signature. Par exemple, l’exclusion de la partie CoreMetadata de la signature permet à une application de modifier certaines propriétés de document sans invalider la signature.

Les parties PrintTicket et DiscardControl sont exclues des signatures créées par la méthode SignDigitally(), bien que ces parties puissent éventuellement être signées d’une manière spécifique à l’application.

Vérification d’une signature de document XPS

Une ou plusieurs signatures peuvent être stockées avec un document XPS. Les signatures peuvent être obtenues à partir de la propriété XpsDocument.Signatures . Chaque signature est représentée par un instance de l’objet XpsDigitalSignature.

Dans l’exemple ci-dessous, seule la première signature de la collection est vérifiée.

     // Open the XPS Document.

     // Obtain the first enumerated signature.

     foreach (XpsDigitalSignature digitalSignature in
              document.Signatures)
     { 
          // Verify the signature object, if present.

          if (digitalSignature.Verify() ==
     System.IO.Packaging.PackageDigitalSignature.VerifyResult.Success)
          {
         //Signature is valid
          }
     }

Références