Infrastructure de signature numérique des conventions d’empaquetage open

 

David Meltzer et Andrey Shur
Microsoft Corporation

Septembre 2006

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

Résumé : Traite du Framework de signature numérique OPC, 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. (12 pages imprimées)

Contenu

Introduction
Composants de l’infrastructure de signature numérique OPC
   Standard de signature numérique XML
   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
   Signature de parties et de relations de package
   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 open Packaging Conventions (OPC) 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 différentes parties dans le package.

Cet article décrit le Framework de signature numérique OPC, 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 inclut une infrastructure pour représenter des signatures numériques et les services permettant de créer et de valider des signatures. L’infrastructure de signature permet à la norme W3C XML Digital Signature d’être appliquée aux parties et relations de package.

À l’aide de l’infrastructure de signature, les propriétaires de formats basés sur un package 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 des formats particuliers et incarner 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 de document (telles que la validation de l’appareil 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 aux nouvelles parties et relations d’être ajoutées à un package, ou une stratégie peut entraîner une invalidation d’une signature si de nouvelles parties ou signatures sont ajoutées à un package.

Cet article suppose qu’il est familiarisé avec la spécification des conventions d’empaquetage open et la syntaxe et le traitement de signature XML de la recommandation W3C.

Composants de l’infrastructure de signature numérique OPC

Standard de signature numérique XML

L’infrastructure de signature pour les packages utilise xml Digital Signature Standard, comme défini dans la syntaxe et le traitement de signature XML de la recommandation W3C. Cette recommandation spécifie les règles de syntaxe et de traitement XML pour produire et stocker 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 n’importe quel 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 hachage en fonction d’un algorithme connu et stocké dans la signature lors de la 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 ou l’entraîne à devenir chiffré (même s’il peut déjà être 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 inattendus.

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 où il est autorisé par la norme XML Digital Signature. Les éléments de signature définis dans l’espace de noms d’empaquetage prennent en charge les fonctionnalités spécifiques aux packages qui augmentent la norme sans le 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 standard et types de contenu », de la spécification OPC.

Composant Origine de signature numérique

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

Composant Signature XML de signature numérique

Les parties signature XML de signature numérique contiennent des marques définies dans la norme W3C Digital Signature standard, ainsi que dans l’espace de noms d’empaquetage. Les parties sont ciblées à partir du code XML de la partie Origine de 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 une partie de certificat distincte. La partie Certificat facultative est ciblée à partir du composant Signature XML avec la relation de certificat de signature numérique . La partie Certificat peut être partagée entre plusieurs parties de signature.

Parties de signature personnalisées

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 signature numérique.

Signature de parties et de relations

La norme XML Digital Signature permet de signer des ressources adressables, qui pour un package sont des parties. L’infrastructure de signature active la signature de parties. Les relations d’un package, stockées dans une partie 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 vous assurer 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 prise pour signer la valeur de 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é, l’infrastructure de signature numérique OPC utilise la valeur de type de contenu pour s’assurer que le type de contenu du composant n’a pas changé depuis que le composant a été signé.

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

La transformation des relations crée une partie relations contenant uniquement l’ensemble de relations spécifié. La partie relations obtenues est utilisée pour la signature et pendant la validation de 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 du Microsoft .NET 3.0 Framework défini dans l’espace de noms System.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 .

Signature de parties et de relations de package

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 connexion à la partie 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, créez d’abord 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 certificat

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 traitent les 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 (tel que défini dans la section « Types standard d’espaces de noms et de contenu » 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 relation dont l’ID unique est 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 les relations du même type sont ajoutées ultérieurement à un package, la signature est invalidée.

Création de l’objet certificat

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 elle est 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() est utilisée pour valider le certificat obtenu, vérifier la structure de certificat, la date d’expiration et l’état de la chaîne. Pour plus d’informations sur l’état de la chaîne, consultez L’énumération X509ChainStatusFlag dans la bibliothèque de classes .NET Framework.

Les développeurs d’applications peuvent utiliser l’état du 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 du package. Cette méthode valide uniquement les signatures, et non 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 utilisant 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 de document XPS.

Documents XPS

Le format de document XPS est basé sur les conventions open packaging, 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 pour les documents XPS décrit l’ensemble de parties et de relations qui doivent être signées afin 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 relations jointes à la partie Origine de 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.

Composants 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éfinies par OPC. Si un composant est signé, les relations qui ciblent celui-ci doivent également être signées.

Type de partie 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é
Composants miniatures Doit être signé
Composant CoreProperties Éventuellement signé
Composant Origine de signature numérique Éventuellement signé
Composant Certificat de signature numérique Éventuellement signé
Composants PrintTicket Éventuellement signé
Ignorer les composantsControl Éventuellement signé

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é de balisage

La spécification de papier XML décrit un moyen d’inclure un autre contenu dans un document XPS : compatibilité des balisages. Un autre contenu est placé dans les éléments de l’espace de noms De compatibilité de 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 validement, 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 juridique peut exiger 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 relation dans la partie relations attachée à la partie Origine de signature numérique. Pour ajouter de nouvelles signatures à un document XPS sans invalider les signatures existantes, cette partie 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

Outre la définition de la création de signature, la stratégie de signature XPS spécifie également comment vérifier une signature comme valide. La stratégie définit les états de validité d’une signature qui inclut une incompatibilité, une rupture, une interrogation et une validité, 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 ?
Incompélisant Non

YES

n/a

Non

n/a

n/a

n/a

n/a

n/a

n/a

Cassé 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 discutables et brisées, 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 inclut 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 avoir 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 composants PrintTicket et DiscardControl sont exclus des signatures créées par la méthode SignDigitally(), bien que ces composants puissent être éventuellement connectés de 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 une 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