Share via


Marco de firma digital de las convenciones de empaquetado abierto

 

David Meltzer y Andrey Shur
Microsoft Corporation

Septiembre de 2006

Se aplica a:
   Marco de firma digital de OPC
   Estándar W3C XML Digital Signature
   Microsoft .NET 3.0 Framework

Resumen: describe el marco de firma digital de OPC, que proporciona información general sobre los componentes del paquete y los servicios auxiliares, así como ejemplos de directivas de firma y su implementación. (12 páginas impresas)

Contenido

Introducción
Componentes del marco de firma digital de OPC
   Estándar de firma digital XML
   Representación de firmas digitales en paquetes
   Firmar partes y relaciones
Compatibilidad de programación con firmas de paquete
   Firmar partes y relaciones del paquete
   Comprobación de certificados y firmas
Directiva de firma de aplicaciones
   Documentos XPS
   Compatibilidad de programación con firmas XPS
Referencias

Introducción

El modelo de empaquetado especificado por open Packaging Conventions (OPC) describe los paquetes, las partes y las relaciones. Los paquetes contienen partes, que contienen contenido y recursos. Las relaciones se definen para conectar el paquete a partes y para conectar varias partes del paquete.

En este artículo se describe el marco de firma digital de OPC, que proporciona información general sobre los componentes del paquete y los servicios auxiliares, así como ejemplos de directivas de firma y su implementación.

El marco de firma incluye una infraestructura para representar firmas digitales y los servicios para crear y validar firmas. El marco de firma permite aplicar el estándar W3C XML Digital Signature a las partes y relaciones del paquete.

Con el marco de firma, los propietarios de formatos basados en paquetes definen e implementan "directivas de firma" específicas de sus formatos. Las directivas especifican cómo firmar y validar el contenido entero de formatos concretos y encarnan cómo se usan las firmas para diferentes flujos de trabajo. De hecho, para un único formato puede haber varias directivas definidas para su uso en diferentes fases del ciclo de vida de un documento.

La directiva de firma de un formato basado en paquetes se expresa en términos de partes de firma y relaciones, y posiblemente otras características de documento (como la validación del dispositivo de pantalla previsto, la profundidad de color o la versión de la aplicación). Una directiva de firma especifica qué componentes de documento se van a firmar y cuáles dejar sin firmar, si los hay. Por ejemplo, se puede implementar una directiva de firma para permitir que se agreguen nuevos elementos y relaciones a un paquete, o una directiva puede hacer que se invalide una firma si se agregan nuevas partes o firmas a un paquete.

En este artículo se supone que está familiarizado con la especificación de convenciones de empaquetado abierto y la sintaxis y el procesamiento de firmas XML de recomendación W3C.

Componentes del marco de firma digital de OPC

Estándar de firma digital XML

El marco de firma de paquetes usa el estándar de firma digital XML, tal como se define en la sintaxis y el procesamiento de firmas XML de recomendación de W3C. Esta recomendación especifica la sintaxis XML y las reglas de procesamiento para producir y almacenar firmas digitales.

El estándar define un tipo de elemento de firma XML, un esquema y requisitos de conformidad para firmar y validar cualquier tipo de recurso digital. El esquema también define elementos para hacer referencia a recursos y especificar algoritmos relacionados con la firma.

Características de firmas digitales

Se puede usar una firma digital para determinar si el contenido firmado ha cambiado desde que se firmó. La firma contiene un manifiesto de contenido que se aplica hash según un algoritmo conocido y almacenado en la firma cuando se crea. Para determinar si el contenido ha cambiado, se vuelve a crear un hash del contenido firmado y se compara con el hash almacenado dentro de la firma.

También se puede usar una firma digital para identificar el firmante del contenido. La identidad del firmante se representa mediante un certificado asociado a la firma. El certificado se puede incrustar en la firma o estar disponible en otro lugar.

Una firma digital no "bloquea" un documento o hace que se cifre (aunque es posible que ya esté cifrado). El contenido del documento permanece sin cambios después de firmarse. Las firmas digitales no impiden que los consumidores no deseados vean el contenido firmado.

Representación de firmas digitales en paquetes

Las aplicaciones incorporan firmas digitales en un paquete mediante una configuración especificada de partes y relaciones.

El marco de firma usa elementos y atributos del espacio de nombres de empaquetado donde lo permite el estándar XML Digital Signature. Los elementos de firma definidos en el espacio de nombres de empaquetado admiten características específicas del paquete que aumentan el estándar sin contradecirlo. Para obtener un resumen de las adiciones, vea la sección "Modificaciones en la especificación de firma digital XML" de la especificación de OPC.

Los elementos del paquete definidos para el marco de firma son la parte Origin, la parte Firma XML y la parte Certificado. Cada tiene un tipo de contenido bien definido. Los tipos de relación bien definidos se usan para conectar partes de firma en un paquete, como se especifica en el Apéndice H, "Espacios de nombres estándar y tipos de contenido", de la especificación de OPC.

Parte de origen de firma digital

La parte Origen de firma digital es el punto de partida para navegar por las firmas de un paquete. La parte Origen de firma digital se dirige desde la raíz del paquete mediante la relación Origen de firma digital . Se pueden seleccionar varias partes de firma desde la parte de origen. Si no hay ninguna firma en el paquete, la parte Origin no estará presente.

Parte de firma XML de firma digital

Las partes de firma XML de firma digital contienen marcado definido en el estándar de firma digital W3C, así como en el espacio de nombres de empaquetado. Las partes se destinan al XML de la parte Origen de la firma digital con la relación Firma digital .

Parte del certificado de firma digital

El certificado X.509 necesario para identificar el firmante, si se coloca en el paquete, puede insertarse en la parte firma XML o almacenarse en una parte de certificado independiente. La parte de certificado opcional se dirige desde el elemento Firma XML con la relación Certificado de firma digital . La parte Certificado se puede compartir entre varias partes de firma.

Elementos de firma personalizados

Los elementos de firma personalizados (específicos de la aplicación) se permiten, pero no los controla, mediante el marco de firma. Un elemento de firma que contiene una forma de firma distinta de una firma XML debe identificarse mediante un tipo de contenido personalizado. Además, se debe usar una relación con un tipo de relación personalizado para dirigirse al elemento desde el elemento Origen de firma digital.

Firmar partes y relaciones

El estándar XML Digital Signature permite la firma de recursos direccionables, que para un paquete son partes. El marco de firma habilita la firma de elementos. Las relaciones de un paquete, almacenadas en una parte de relaciones, se pueden firmar a la vez o se puede especificar un subconjunto de relaciones para firmar.

El tipo de contenido de un elemento está firmado, junto con el contenido del elemento, para asegurarse de que se usará o representará un elemento en un paquete firmado válidamente según lo previsto. Dado que el tipo de contenido no es un recurso direccionable, se toma un enfoque específico del paquete para firmar el valor del tipo de contenido. Cuando se firma el paquete, el tipo de contenido de cada parte firmada se almacena en el componente de consulta del URI que hace referencia a la parte firmada. Cuando se consume el paquete, el marco de firma digital de OPC usa el valor de tipo de contenido para asegurarse de que el tipo de contenido del elemento no ha cambiado desde que se firmó el elemento.

Cuando la parte de relaciones se firma como un todo, se firman todas las relaciones definidas en esa parte. Para admitir directivas de firma que permitan que algún contenido de un paquete cambie sin invalidar la firma, el marco de firma proporciona un mecanismo para firmar relaciones especificadas. Para firmar las relaciones especificadas, el marco de firma usa una transformación especial, la transformación relaciones (consulte Transformar algoritmos).

La transformación relaciones crea una parte de relaciones que contiene solo el conjunto de relaciones especificado. La parte de relaciones obtenida se usa para firmar y durante la validación de firmas.

Compatibilidad de programación con firmas de paquete

Para firmar y validar firmas, las aplicaciones pueden usar las clases .NET 3.0 PackageDigitalSignatureManager. Las clases específicas del paquete, definidas en el espacio de nombres System.IO.Packaging , se basan en las clases de firma digital de Microsoft .NET 3.0 Framework definidas en el espacio de nombres System.Security.Cryptography.Xml .

La clase PackageDigitalSignatureManager se usa para crear y validar firmas y colocar la infraestructura de firma en un paquete. La firma se representa mediante un objeto basado en la clase PackageDigitalSignature .

Firmar partes y relaciones del paquete

Una aplicación define una lista de partes y relaciones para firmar según su directiva de firma. A continuación, la aplicación llama al método PackageDigitalSignatureManager.Sign() para crear la firma y agregar la infraestructura de firma al paquete.

En el código de ejemplo siguiente se muestra cómo firmar todas las partes del paquete, excepto las partes de relaciones, firmar todas las relaciones existentes que se originan en la raíz del paquete e insertar el certificado usado para iniciar sesión en el elemento Firma XML. El código de ejemplo supone que no existen firmas en el paquete al principio y solo se aplica una firma antes de la comprobación.

Inicio del proceso de firma

Para empezar a trabajar con firmas en el paquete, primero cree un PackageDigitalSignatureManager, como se muestra a continuación.

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

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

Opciones de inserción de certificados

Un certificado se puede representar como una cadena incrustada en la propia firma, como una parte independiente del paquete o como un recurso fuera del paquete. Si el certificado se va a colocar dentro del paquete, una aplicación especifica cómo se conservará el certificado mediante las opciones de inserción de la propiedad PackageDigitalSignature.CertificateOption . Después de crear la clase PackageDigitalSignatureManager , se establecen las opciones de inserción del certificado, como se muestra en el código de ejemplo siguiente.

    //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;

Lista de elementos firmados

La lista de partes que se van a firmar se especifica mediante los URI que direcciona los elementos. En este ejemplo, todas las partes del paquete se firmarán excepto las partes de relaciones, que se filtran mediante el método 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);
  }

Lista de relaciones firmadas

Las relaciones individuales se firman mediante la transformación relaciones. Las relaciones de firma de esta manera permiten agregar nuevas relaciones al paquete sin invalidar la firma.

Las relaciones se seleccionan para firmar mediante la creación de una lista de objetos PackageRelationshipSelector que se usarán en el momento de la firma. Los objetos PackageRelationshipSelector se pueden crear como un grupo por tipo de relación (tal como se define en la sección "Espacios de nombres estándar y tipos de contenido" de las convenciones de empaquetado abierto) o se pueden crear individualmente especificando el identificador de relación, como en el ejemplo siguiente.

     //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));
            }

Al crear un PackageRelationshipSelector con PackageRelationshipSelectorType.Id, se seleccionará la relación que tenga el identificador único especificado para firmar. Al crear un selector con PackageRelationshipSelectorType.Type, se seleccionan todas las relaciones con el tipo especificado para firmar. Si las relaciones del mismo tipo se agregan más adelante a un paquete, la firma se invalidará.

Creación del objeto Certificate

Antes de firmar, se obtiene un certificado X.509 válido mediante la creación de instancias de un objeto de tipo System.Security.Cryptography.X509Certificates.X509Certificate2. Este objeto se pasa al método PackageDigitalSignatureManager.Sign() en el momento de la firma. Para obtener más información sobre cómo crear objetos de certificado, vea el espacio de nombres System.Security.Cryptography.X509Certificates .

Aplicación de la firma

Después de crear la lista de partes y relaciones para firmar y obtener el objeto de certificado, una aplicación llama al método 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();

Cuando se llama al método Sign(), se genera y almacena el hash en el manifiesto de firma y se crea la parte de firma. Si la infraestructura de firma ya existe en el paquete, se agregará la nueva parte de firma (si se permite). Si la infraestructura aún no existe en el paquete, el método Sign() crea la infraestructura y la coloca en el paquete.

Comprobación de certificados y firmas

Las aplicaciones pueden comprobar un certificado o una firma. Antes de comprobar la firma, se debe comprobar el certificado. El objeto que representa la firma en el paquete , PackageDigitalSignature, tiene una propiedad "Signer" que devuelve el certificado utilizado para crear esa firma, si está en el paquete. Si el certificado no está incrustado en el paquete, la aplicación obtiene el certificado de una ubicación conocida para la aplicación.

El método PackageDigitalSignatureManager.VerifyCertificate() se usa para validar el certificado obtenido, comprobando la estructura del certificado, la fecha de expiración y el estado de la cadena. Para obtener más información sobre el estado de la cadena, vea Enumeración X509ChainStatusFlag en la biblioteca de clases de .NET Framework.

Los desarrolladores de aplicaciones pueden usar el estado del certificado para admitir sus directivas de firma. Por ejemplo, una aplicación puede especificar que solo se aceptan certificados emitidos después de determinadas fechas.

El método PackageDigitalSignatureManager.VerifySignatures() se usa para validar todas las firmas del paquete. Este método solo valida las firmas, no los certificados asociados a las firmas.

El código de ejemplo siguiente se puede usar para validar el certificado y la firma colocados en el paquete en los ejemplos de firma. El código de ejemplo supone que no se han agregado firmas adicionales al paquete.

    // 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();

Directiva de firma de aplicaciones

Las aplicaciones que usan formatos basados en paquetes definen sus propias directivas como parte del marco de firma. La directiva viene determinada por los tipos de elementos y los requisitos de flujo de trabajo del formato. En esta sección, la directiva de firma se describe para un formato basado en paquetes de Microsoft: el formato de documento XPS.

Documentos XPS

El formato de documento XPS se basa en las convenciones de empaquetado abierto, como se especifica en la especificación de papel XML. La especificación de papel XML define la directiva para firmar documentos XPS. Dentro de esa directiva, hay opciones de firma disponibles para admitir características de aplicación o flujo de trabajo.

Directiva de firma para paquetes de documentos XPS

La directiva de firma para documentos XPS describe el conjunto de partes y relaciones que se deben firmar para que se pueda validar el contenido. Como parte de esta directiva, una aplicación puede crear una firma que incluya opcionalmente una combinación de partes concretas que son adjuntas al contenido, como la parte CoreProperties. Firmar estas partes impedirá que se cambien sin invalidar la firma. Además, las aplicaciones pueden firmar opcionalmente la parte de relaciones asociada al elemento Origen de firma digital en la firma, lo que prohíbe que se agreguen nuevas firmas al documento sin invalidar la firma.

Para que una firma sea válida, la directiva de firma de documentos XPS requiere que determinadas partes y relaciones se incluyan en la firma. No se pueden firmar partes o relaciones no reconocidas. Al comprobar una firma, una aplicación debe confirmar que se firman todas las partes y relaciones necesarias.

Elementos del documento XPS que se van a firmar

La tabla siguiente contiene la lista de partes que deben estar firmadas en todos los documentos XPS y las partes que están firmadas opcionalmente. En el caso de las relaciones, la directiva de firma XPS especifica que las relaciones necesarias (relaciones destinadas a partes necesarias) siempre se firman mediante la transformación de relaciones definidas por OPC. Si una parte está firmada, las relaciones que tienen como destino también deben estar firmadas.

Tipo de elemento Directiva de
Elemento FixedDocumentSequence Debe estar firmado
Elemento FixedDocument Debe estar firmado
Elementos DocumentStructure Debe estar firmado
Elemento SignatureDefinitions Debe estar firmado
Elementos FixedPage Debe estar firmado
Elementos de recursos necesarios (como fuentes, imágenes) Debe estar firmado
Elementos StoryFragments Debe estar firmado
Elementos en miniatura Debe estar firmado
Elemento CoreProperties Opcionalmente, firmado
Parte de origen de firma digital Opcionalmente, firmado
Parte del certificado de firma digital Opcionalmente, firmado
Elementos PrintTicket Opcionalmente, firmado
Elementos DiscardControl Opcionalmente, firmado

Para obtener más información sobre la directiva de firma XPS, vea la sección "Características del paquete de documentos XPS: Firmas digitales: reglas de firma" en la especificación de papel XML.

Directiva de firma de compatibilidad de marcado

La especificación de papel XML describe un medio para incluir contenido alternativo en un documento XPS: compatibilidad de marcado. El contenido alternativo se coloca dentro de los elementos del espacio de nombres Compatibilidad de marcado. Por directiva, los documentos XPS que tienen atributos y elementos de compatibilidad de marcado no se pueden firmar válidamente, a menos que la aplicación de firma reconozca todas las alternativas de contenido como equivalentes. Solo los documentos XPS que contienen elementos y atributos que se reconocen se pueden firmar o validar.

Contrafirmas

Se puede aplicar más de una firma al contenido de un documento XPS. Por ejemplo, el contenido que representa un contrato legal puede requerir que varias personas apliquen sus firmas, lo que indica el contenido firmado y la identidad del firmante.

Al agregar una nueva firma, siempre se crea una nueva relación dentro de la parte de relaciones asociada al elemento Origen de firma digital. Para agregar nuevas firmas a un documento XPS sin invalidar las firmas existentes, esta parte de relaciones debe permanecer sin firmar (aunque se puede firmar un subconjunto de relaciones). Si la parte de relaciones se incluye en una firma, todas las firmas aplicadas posteriormente invalidarán esa firma.

Validación de firmas XPS

Además de definir la creación de firmas, la directiva de firma XPS también especifica cómo comprobar una firma como válida. La directiva define los estados de validez de una firma que incluyen incompliant, broken, questionable y valid, como se muestra en la tabla siguiente.

Estado de firma ¿Se firman todas las partes y relaciones necesarias? ¿La firma solo incluye contenido reconocido? ¿Se comprueba el hash del contenido firmado? ¿Se reconoce el contenido de compatibilidad de marcado firmado? ¿El certificado es válido?
Incompliant No

N/D

No

N/D

N/D

N/D

N/D

N/D

N/D

Interrumpido No N/D N/D
Cuestionable

No

N/D

No

Válido

El Visor XPS muestra firmas XPS preguntables y rotas, así como firmas XPS válidas. No se enumeran las firmas no conformes.

Compatibilidad de programación con firmas XPS

Al trabajar con un documento XPS, las aplicaciones pueden usar los métodos de la clase XpsDigitalSignature . Esta clase se basa en la clase PackageDigitalSignature e incluye métodos que siguen los algoritmos y los requisitos especificados en la especificación de firma digital XPS. Los métodos de firma y validación comprueban que todos los elementos y relaciones necesarios de un documento XPS estén firmados.

Firmar un documento XPS

El método XpsDocument.SignDigitally() se usa para firmar un documento XPS. Antes de llamar al método , una aplicación debe tener un certificado X.509, que se puede obtener mediante el objeto 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 se puede usar para especificar restricciones adicionales para una firma, en función de la directiva de firma. Este parámetro especifica si se van a excluir los elementos CoreMetadata o SignatureOrigin de la firma. Las partes excluidas se pueden modificar posteriormente sin invalidar la firma. Por ejemplo, la exclusión del elemento CoreMetadata de la firma permite a una aplicación cambiar algunas propiedades de documento sin invalidar la firma.

Los elementos PrintTicket y DiscardControl se excluyen de las firmas creadas por el método SignDigitally(), aunque estas partes pueden estar firmadas opcionalmente de forma específica de la aplicación.

Comprobación de una firma de documento XPS

Una o varias firmas se pueden almacenar con un documento XPS. Las firmas se pueden obtener de la propiedad XpsDocument.Signatures . Cada firma se representa mediante una instancia del objeto XpsDigitalSignature .

En el ejemplo siguiente, solo se comprueba la primera firma de la colección.

     // 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
          }
     }

Referencias