PKCS #7

El estándar pkcs #7 es un conjunto de normas para firmar y encriptar documentos, normalmente usado en el mail para la autenticidad y privacidad de los datos contenidos en ellos.
De objetos PKCS #7 podemos encontrar varios tipos: Para comprender mejor estos tipos de datos, debemos de adentrarnos más en el conocimiento de este estándar.

Tipo de contenido "data":

El tipo data es solo la información en una cadena de octetos, sin ningún tipo de manipulación criptográfica.

Tipo de contenido "signed data":

Es cualquier tipo de datos que estén firmados por uno o varios firmantes mediante un resumen de los datos y su posterior encriptación utilizando la clave privada de cada firmante sobre el resumen de los dato, a esta encriptación del resumen es a lo que se llama firma electrónica.
Para crear un tipo signed data se siguen los siguientes pasos: Los pasos que debe realizar el destinatario son más simples:

Tipo de datos en ASN.1 SignedData:

SignedData::= SEQUENCE {
    version Version;
    digestAlgorithms DigestAlgorithmsIdentifiers,
    contentInfo ContentInfo,
    certificates
        [0] IMPLICIT ExtendedCertificatesAndCertificates
            OPTIONAL,
    crls
        [1] IMPLICIT CertificateRevocationLists
            OPTIONAL,
    signerInfos SignerInfos
    }
DigestAlgorithmIdentifiers ::= SET OF DigestAlgorithmIdentifier
SignerInfos ::= SET OF SignerInfo

Donde:

  • version es la versión del estándar que se está utilizando
  • digestAlgorithms son un conjunto de identificadores de algoritmos para resúmenes - inclusive ninguno -. Cada elemento identifica el algoritmo utilizado para resumir el contenido y los parámetros que se han utilizado.
  • contentInfo es el objeto que queremos firmar.
  • certificates es un conjunto de certificados extendidos tipo PKCS#6 y certificados X.509. Se intenta que el conjunto sea suficiente para contenet certificados hasta una CA raiz reconocida para todos los firmantes que están en el campo SignersInfo. Pueden haber también certificados suficientes para que la CA raiz no sea única, en el caso de que fuera única, los certificados podrán ser verificados por otros medios.
  • crls es un conjunto de listas de certificados revocados.
  • signersInfo es un conjunto de información sobre los firmantes, pueden haber cualquier número de de elementos, incluido ninguno.
  • Tipo de datos en ASN.1 SignerInfo:

    SignerInfo ::= SEQUENCE {
        version Version,
        issuerAndSerialNumber IssuerAndSerialNumber,
        digestAlgorithm DigestAlgorithmIdentifier,
        authenticatedAttributes
            [0] IMPLICIT Attributes OPTIONAL,
        digestEncryptionAlgorithm
            DigestEncryptionAlgorithmIdentifier,
        encryptedDigest EncryptedDigest,
        unautenticatedAttributes
            [1] IMPLICIT Attributes OPTIONAL
        }
    EncryptedDigest ::= OCTET STRING

    Donde:

  • version  es la version de la sintaxis que se está utilizando
  • issuerAndSerialNumber precisa el certificado del firmante - por supuesto el nombre del mismo y su clave pública - mediante el nombre de la CA y el número de serie del certificado.
  • digestAlgorithm identifica el algoritmo utilizado para resumir el contenido del mensaje y los atributos que se han querido autenticar con los parametros que se han utilizado al resumir.
  • authenticatedAttributes son un conjunto de atributos que han sido firmados. Este campo es opcional, pero debe estar presente si el tipo de contenido del campo contentInfo no es data. Si el campo está, entonces debe tener como mínimo dos atributos:
  • digestEncryptionAlgorithm identifica el algoritmo utilizado para encriptar el mensaje y la información suplementaria con la clave privada del firmante.
  • encryptedDigest es el resumen y la información adicional encriptados.
  • unautenticatedAttributes es un conjunto de atributos que no han sido firmados - este campo no se suele utilizar -.

  • Nota: los atributos están definidos en el estándar del PKCS#9.

    Ejemplo de objeto PKCS #7 tipo firma

    Proceso de resumen de mensajes:

    Este proceso calcula un resumen del mensaje que va a ser firmado o el mensaje y los atributos que van a ser firmados. En cada caso, la entrada serán los objetos a firmar o, especificamente, los bytes contenidos en el subcampo ContentInfo del campo content codificado en DER (base64) que se quiere firmar - sólo los bytes de datos se resumirán, no los identificadores de los bytes o los bytes de longitud-.
    El resultado del resumen depende de que el campo authenticatedAttributes esté presente, si no está, el resumen se hará solo del contenido y si está, el resultado será el resumen de la codificación en DER del valor Atributtes contenida en el campo authenticatedAttributes, entonces en el campo Attributes debe estar también el tipo de contenido y el resumen de ese tipo como atributo.
    Cuando el contenido a firmar es de tipo data y el campo authenticatedAttributes no está, el resumen se hará solo del valor de data. Esto tiene la ventaja de que la longitud del contenido a firmar no debe ser conocida a prioori en el proceso de encriptación.
    Aunque los bytes identificadores y la longitud no estén resumidos, están protegidos por otros medios; los bytes de longitud están protegido por la naturaleza de los algoritmos de resumen, ya que es computacionalmente imposible encontrar dos mensajes distintos que tengan el mismo resumen, además, asumiendo que el tipo de contenido unicamente determine los bytes identificadores, éstos están protegidos implícitamente por una de estas dos vías: por la inclusión del tipo de contenido en los atributos autenticados o por el uso de la compatibilidad con el PEM, que implica que el tipo de contenido es data.
     

    Proceso de cifrado de mensajes:

    Las entradas a este proceso son el resumen en sí del mensaje y el identificador del algoritmo que se ha utilizado y la salida es el cifrado con la clave privada del firmante de la codificación en BER del valor de tipo DigestInfo:

    DigestInfo ::= SEQUENCE {
        digestAlgorithm DigestAlgorithmIdentifier,
        digest Digest
        }
    Digest ::= OCTET STRING

    Donde

  • digestAlgorithm es el algoritmo que se ha utilizado para resumir el mensaje y los identificadores autenticados, lógicamente debe ser el mismo que el presente en el campo digestAlgorithm de la estructura SignerInfo.
  • digest es el resumen en sí.
  • Tipo de contenido "enveloped-data":

    Este tipo de contenido consiste en un contenido cifrado de cualquier tipo junto con la llave de sesión cifrada con la/s clave/s pública/s de el/los destinatario/s. Ésta combinación es lo que se conoce como un sobre digital. para cada destinatario. Cualquier tipo de dato se puede meter en un sobre y enviarlo a cualquier número de destinatarios. Normalmente, el uso que  se dará a este tipo será el envío a varios destinatarios de contenido cifrado del tipo data, digested-data o signed-data.

    Para crear un "sobre" necesitamos hacer los siguientes pasos:

  • Se genera de forma aleatoria una clave de sesión para un algoritmo de encriptación en particular.
  • Para cada destinatario, la clave de sesión se cifra con la clave pública del destinatario
  • Para cada destinatario, la clave de sesión y alguna otra información propia del destinatario se agrupa en un valor del tipo RecipientInfo.
  • El contenido se cifra con la llave de sesión
  • Los valores del tipo RecipientInfo - uno por cada destinatario - se juntan con el contenido cifrado del mensaje original, creándose así el "sobre"

  •  

     

    El proceso a seguir por el destinatario es el sigueinte:

  • El destinatario abre el "sobre" descifrando la única parte que puede descifrar - la que hace referencia a él ya que esá cifrada con su clave pública - y descifra la clave de sesión.
  • Se descifra el contenido utilizando esta clave de sesión que se ha descifrado antes.

  • La llave privada del destinatario está referenciada mediante el nombre de la CA - issuer- y el número de serie del certificado, entonces únicamente distingue como válido ese certificado al que referencia.

    Tipo de datos en ASN.1 EnvelopedData:

    La estructura de datos del tipo EnvelopedData en ASN.1 es la siguiente:

    EnvelopedData ::= SEQUENCE {
        version Version,
        recipientInfos RecipientInfos,
        encryptedContentInfo EncriptedContentInfo
        }
    RecipientInfos ::= SET OF RecipientInfo
    EncryptedContentInfo ::= SEQUENCE {
        contentType ContentType,
        contentEncryptionAlgorithm ContentEncryptionAlgorithmIdentifier,
        encryptedContent
            [0] IMPLICIT EncryptedContent OPTIONAL
        }
    EncryptedContent ::= OCTET STRING

    Donde:

  • version es la versión de la sintaxis con la que se ha hecho el objeto.
  • recipientInfos es el conjunto de información sobre los destinatarios - debe haber al menos uno - .
  • encryptedContentInfo es el contenido del mensaje cifrado e información sobre el cifrado del mismo. Dentro de esta estructura encontramos:

  • Ejemplo de cifrado para un destinatario

    Ejemplo de cifrado para varios destinatarios
     

    Tipo de datos en ASN.1 RecipientInfo:

    La información para cada destinatario se agrupa en una estructura del tipo RecipientInfo:

    RecipientInfo ::= SEQUENCE {
        version Version,
        issuerAndSerialNumber IssuerAndSerialNumber,
        keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier,
        encriptedKey EncryptedKey
        }
    EncryptedKey ::= OCTET STRING

    Cuyo significado es:

  • version es la versión de la sintaxis que se está utilizando
  • issuerAndSerialNumber especifica el certificado del destinatario mediantela información sobre la CA que ha expedido el certificado, es decir su nombre y el número de serie de ese certificado
  • keyEncryptionAlgorithm identifica el algoritmo con el que se ha cifrado, mediante la clave pública del destinatario, la clave de sesión.
  • encrytptedKey es la clave de sesión cifrada.
  • Proceso de cifrado de mensajes:

    La entrada al proceso es el contenido que quiere ser metido en un "sobre", especificamente la entrada puede ser también los bytes de contenido de un tamaño definido codificados en BER contenidos en el subcampo content del valor ContentInfo de los datos a cifrar. Sólo los bytes de contenido de la cofdificación BER se cifran, no los bytes identificativos o los bytes de longitud, ya que no son representativos en este caso.
    Cuando el tipo de datos a cifrar es data, sólo el valor de los datos se cifra, esto tiene la ventaja de quue la longitud de los datos no necesita ser conocida a priori en el proceso de cifrado.
    Como hemos dicho antes, los bytes identificativos y los de longitud no se encriptan; no por eso dejan de estar protegidos, ya que los bytes de longitud están protegidos implícitamente por le proceso de cifrado. Los identificativos no están protegidos, ya que pueden ser recuperados por el contenido, asuminedo que el tipo de contenido determina unívocamente los bytes identificativos. La protección de los bytes identificativos y los de longitud implica el uso del tipo signed-and-enveloped-data o que se utilicen el digested-data y después el enveloped-data.

    Proceso de cifrado de la clave de sesión:

    La entrada, lógicamente, es la llave de sesión que se ha utilizado y la salida, la clave de sesión cifrada con la clave pública del destinatario.

    Tipo de contenido "signed-and-enveloped-data":

    Este tipo consisten en un contenido cifrado de cualquier tipo, una llave de sesión cifrada para uno o más destinatarios y los resúmenes doblemente cifrados del mensaje para uno o más firmantes - doblemente cifrados, ya que se cifran primero para firmar con la clave privada del firmante y luego, se cifran con la llave de sesión del cifrado. Así creamos un sobre - ya que el uso de la combinación del cifrado del mensaje y el cifrado de la llave de sesión es un sobre digital - firmado o autenticado - ya que el resumen encriptado del mensaje con la clave privada del remitente es una firma digital -.
    Cualquier tipo de contenido puede ser metido en un sobre y además firmado por cualquier número de firmantes en paralelo.

    El proceso con el que se crea este tipo de datos es el siguiente:

  • Se genera una llave de sesión aleatoria para un algoritmo de encriptación en particular
  • Para cada destinatario se cifra la llave de sesión con su clave píblica
  • Para cada destinatario, se junta la llave de sesión encriptada junto con información adicional del destinatario en una estructura RecipientInfo.
  • Para cada firmante, se calcula un resumen del mensaje utilizando el algoritmo que desee el firmante, si dos firmantes utilizan un mismo algoritmo, sólo se calcula una sola vez.
  • Para cada firmante, el resumen y otra información adicional se cifra con la clave pública propia de cada firmante para después ser cifradda de nuevo con la llave de sesión utilizada.
  • Para cada firmante, el resumen doblemente cifrado se junta con otra información adicional del firmante en una estructura de datos SignerInfo.
  • El contenido del mensaje se cifra con la llave de sesión.
  • Los resumenes del mensaje de todos los firmantes, las estructuras SignerInfo y RecipientInfo de todos los destinatarios y firmantes se juntan con el mensaje encriptado en una estructura SignedAndEnvelopedData.

  •  

     

    El proceso a seguir por un destinatario es:

  • Verificar las firmas en dos pasos
  • Leer el mensaje previamente descifrado
  • Tipo de datos en ASN.1 SignedAndEnvelopedData:

    La estructura de datos SignedAndEnvelopedData en ASN.1 es la que sigue:

    SignedAndEnvelopedData ::= SEQUENCE {
        version Version,
        recipientInfos RecipientInfos,
        digestAlgorithms DigestAlgorithmsIdentifiers,
        encryptedContentInfo EncriptedContenInfo,
        certificates
            [0] IMPLICIT ExtendedCertificatesAndCertificates OPTIONAL,
        crls
            [1] IMPLICIT CertificateRevocationLists OPTIONAL,
        signerInfos SignerInfos
        }

    Donde:

  • version es el número de versión que se utiliza en la sintaxis.
  • recipientInfos es un conjunto de información de los destinatarios, debe haber al menos uno.
  • digestAlgorithms es el conjunto de identificadores de algoritmos que se han utilizado para resumir el mensaje.
  • encryptedContentInfo es el contenido del mensaje cifrado
  • certificates es un conjunto de certificados extendidos PKCS#6 y certificados X.509
  • crls es un conjunto de listas de certificados revocados
  • signerInfos es el conjunto de información sobre los firmantes, debe haber al menos un elemento en esta lista. Los valores de esta estructura son los mismos que en el tipo SignerInfo anteriormente explicado exceptuando el campo encryptedDigest.
  • Proceso de resumen-cifrado:

    La entrada de este proceso es la misma que la del proceso de resumen de mensaje citado con anterioridad a este punto. Específicamente el proceso puede tener dos pasos, el primero es como en el resumen del mensaje y el segundo es el cifrado del resumen que ha salido del paso uno con la llave de sesión. En este caso no hay una codificación en BER entre los dos pasos, sino que el valor de salida del primer paso es directamente el de entrada del segundo.

    Tipo de contenido "digested-data":

    Este tipo consiste en un contenido de cualquier tipo y su resumen correspondiente. Su intención es la de garantizar la integridad del contenido y ser entrada a procesos de crear objetos del tipo enveloped-data.
    El proceso de creación es el siguiente:
  • Un resumen del contenido se calcula con el algoritmo que se desee.
  • El contenido y el resumen se juntan en una estructura del tipo DigestedData.
  • Tipo de datos en ASN.1 DigestedData:

    DigestedData ::= SEQUENCE {
        version Version,
        digestAlgorithm digestAlgorithmIdentifier,
        contentInfo ContentInfo,
        digest Digest
        }
    Digest ::= OCTET STRING

    Que significan:

  • version es la version de la sintaxis que se está utilizando
  • digestAlgorithm es el identificador del algoritmo con el que se ha realizado el resumen
  • contentInfo es el contenido que se ha resumido
  • digest es el resumen del contenido
  • Tipo de contenido "encrypted-data":

    Consiste en un contenido de cualquier tipo que se haya cifrado, distinto al enveloped-data, no contiene ningúna referencia al destinatario - ya que puede no existir - ni referencias a llaves de sesión. Las medidas de seguridad en cuanto a llaves , se suponen tomadas por otros medios. Su finalidad es la de encriptar contenido localmente, por eso la llave de cifrado sea simplemente una password.

    Tipo de datos en ASN.1 EncryptedData:

    EncryptedData ::= SEQUENCE {
        version Version,
        encryptedContentInfo EncryptedContentInfo
        }
    Siendo :
  • version es la versión con la que se ha creado el objeto.
  • encryptedContentInfo es la información cifrada
  • Identificadores de objetos:

    El estándar puesto en los RFC's define siete identificadores de objetos : pkcs-7 , data, signedData, envelopedData, signedAndEnvelopedData, digestedData y encryptedData, explicados en este documento siendo su estructura:

    pkcs-7 OBJECT IDENTIFIER ::= { iso (1) member-body (2) US (840) rsadsi (113549) pkcs (1) 7 }
    data OBJECT IDENTIFIER ::= { pkcs-7 1}
    signedData OBJECT IDENTIFIER ::= { pkcs-7 2}
    envelopedData OBJECT IDENTIFIER ::= { pkcs-7 3}
    signedAndEnvelopedData OBJECT IDENTIFIER ::= { pkcs-7 4}
    digestedData OBJECT IDENTIFIER ::= { pkcs-7 5}
    encrypedData OBJECT IDENTIFIER ::= { pkcs-7 6}

    Ejemplos de algunos de estos identificadores de objetos:

    OBJECT IDENTIFIER data (1 2 840 113549 1 7 1)
    OBJECT IDENTIFIER signedData (1 2 840 113549 1 7 2)
    OBJECT IDENTIFIER envelopedData (1 2 840 113549 1 7 3)