[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: PKCS#7 in PKIX-3



Death Rays from Mars made Housley, Russ <housley@spyrus.com> write:
 
>I think that we are near concensus on this point.  A single encapsulation
>mechanism would be ideal.  PKIX Part 3 contains one suggestion, and PKCS #7
>contains another.  Carlise provided an analysis for the PKIX Part 3 approach.
>PKCS #7 has a market share that should not be ignored, and the specification
>is open for reivew and update.
 
Just to further muddy the water, I've been using a format which is (IMHO) an
improvement on PKCS #7 (it fixes a few problems in the PKCS format and is
easier to use).  In case anyone's interested, I've included the ASN.1
specification for the encapsulation below.
 
Peter.
 
-/ The basic content type.  PKCS #7 defines content as a sequence of { OID,
   ANY DEFINED BY } and then nests one of a number of different grand unified
   data types (signed, enveloped, signedAndEnveloped, etc) inside this.  This
   doesn't allow for useful extensions such as compressed data or (currently)
   signed then encrypted data, and has the nasty problem of a combinatorial
   explosion of data types (which is also endemic among other RSADSI products
   which use grand unified types) such as SignedAndEncryptedButNotCompressed,
   SignedAndEncryptedAndCompressed, SignedAndEncrypted, EncryptedAndSigned,
   etc etc.  A neater solution is to provide at the start of the content a
   SEQUENCE OF ContentInfo records which define the transformations to be
   applied to the content.  The contentInfo field encodes in one step a
   transformation which would normally be encoded using nested ASN.1 objects,
   so that for example the transformation:
 
    Sign( Compress( data ))
 
   would be encoded as:
 
    Sign, Compress( data )
 
   The reason for trying to reduce the level of nesting as much as possible
   is that nested, indefinite-length ASN.1 data types are messy to encode and
   lead to unnecessary message expansion.  This form of encapsulation is
   known as "logical wrapping", in which a single physical level of wrapping
   is used to provide the equivalent of multiple logical levels of wrapping.
 
   The sequence of ContentInfo fields encodes the progression of levels in
   which the data is encased.  For example a contentInfo field of { Signed,
   Compressed } would specify that the content should be signature checked
   and then decompressed to recover the original data (ie the compressed data
   has been signed).  In contrast a contentInfo field of { Compressed, Signed
   } would specify that the content should be decompressed and then signature
   checked (ie the decompressed data has been signed).
 
   This system can be used to encode arbitrary transformations on the
   content, with arbitrary logical nesting and an arbitrary processing order.
 
   One disadvantage of the one-size-fits-all basic content type is that two
   fields which are specific to two of the content types must be added.  The
   signatures field is used for the Signed data type to contain the
   signatures on the data (which may be empty if the signatures are stored
   separately), and the padding field is used for the Encrypted data type to
   contain optional message padding /-
 
Content ::= SEQUENCE {
    contentInfo     SEQUENCE OF ContentInfo,
                                    -- Transformation to apply to the content
    content         OCTET STRING,   -- Data payload
    signatures  [0] SET OF Signature OPTIONAL,  -- Signature(s) on the data
    padding     [1] OCTET STRING OPTIONAL       -- Data padding
    }
 
ContentInfo ::= CHOICE {
    nestedData  [0] IMPLICIT NestedDataInfo,
    encryptedData
                [1] IMPLICIT EncryptedDataInfo,
    signedData  [2] IMPLICIT SignedDataInfo,
    compressedData
                [3] IMPLICIT CompressedDataInfo,
    ...
    }
 
-/ Nested data.  This specifies that the data payload contains nested content
   which should be further processed.  This is usually used after the
   encryptedData type to specify that the decrypted data should be further
   processed.  The use of a BOOLEAN is somewhat unnecessary since the mere
   presence of the nestedData field is enough to convey the necessary
   information, however providing the field and setting the value to FALSE
   can also convey the information "I want to bloat up the header
   unnecessarily" /-
 
NestedDataInfo ::= BOOLEAN
 
-/ Encrypted data.  The encryptionKeyInfo contains the session key and bulk
   data encryption algorithm details, encrypted with zero or more public or
   conventional key encryption keys.  If the set is empty, the session key
   must be supplied by some other means.  If the set is nonempty, the session
   key may be reconstructed by decrypting one of the EncryptionKeyInfo
   records with the appropriate private key or conventional KEK.  Public and
   conventional KEK's may be mixed, so that a single message could be
   decrypted with one or more conventional and/or private keys.
 
   The IV is always present as a fixed-length string to obscure the details
   of the algorithm and mode being used.  If necessary it is extended to more
   than CRYPT_MAX_IVSIZE bytes by padding to the right with 0 bits /-
 
EncryptedDataInfo ::= SEQUENCE {
    encryptionKeyInfo
                    SET OF EncryptionKeyInfo,
                                    -- Encrypted seesion key, may be empty set
    keyCookie   [0] IMPLICIT KeyCookie OPTIONAL,            -- Key cookie
    iv              OCTET STRING (SIZE(CRYPT_MAX_IVSIZE))   -- IV
    }
 
-/ Signed data.  The digestAlgorithms field contains information on which
   types of message digest to compute for the data in order to allow the
   signature check to be performed once the end of the data has been reached.
   This is stored before the data itself to allow for one-pass processing.
   The signatureCookie field is used to tie the signed data to the signature
   or signatures associated with it if they are stored separately /-
 
SignedDataInfo ::= SEQUENCE {
    digestAlgorithms
                    DigestAlgorithmIdentifiers,
                                    -- Information on digests for sig.check
    signatureCookie
                [0] IMPLICIT SignatureCookie OPTIONAL   -- Signature cookie
    }
 
-/ Compressed data.  This provides information on the compression algorithm
   used and any necessary parameters.  Unfortunately the only ISO-approved
   algorithms are peculiar, usually patented or otherwise restricted ones
   (check if Zip has an OID) /-
 
CompressedDataInfo ::= SEQUENCE {
    compressionAlgorithm
                    CompressionAlgorithmIdentifier  -- Compression algorithm
    }