number of crl certificate(s) or pem certificate(s) present in p7s file

Q. How can we find out the number of CRL files or number of PEM files that can be generated from a P7S file?

I understand ( from here ) that the data that is contained in a P7S file is nothing but the encoded(in ASN1, DER format) data of PEM file.

So, if have a P7S file which encoded in (in ASN1, DER format), i use some OpenSSL commands to get ASN1PARSE data and from which i get CRL(s) and at last i get PEM(s).

I know ASN1PARSE when used with OpenSSL gives some text file which contains some offsets , header lenghts and lengths, by using which we extract the above mentioned CRL(S) and PEM(S).

Now my question is , as mentioned in first line of post, how can i know i am generating the right number of files(crls,pems) from P7S file?


Solution 1:

A PKCS#7 file, nowadays defined in Cryptographic Message Syntax (RFC 5652), can hold many certificates and many CRLs.

The normal way to extract them with OpenSSL is to use:

openssl pkcs7 -in file.pem -print_certs -out certs.pem

or, if the input file is DER:

openssl pkcs7 -inform DER -in file.p7s -print_certs -out certs.pem

The man page states:

-print_certs
prints out any certificates or CRLs contained in the file. They are preceded by their subject and issuer names in one line format.

There is no need to parse them with asn1parse unless you're debugging or a glutton for punishment.

The above outputs a single file containing all the certificates and CRLs. If you want individual files you should be able to pipe the output through awk, with something similar to:

openssl pkcs7 -inform DER -in file.p7s -print_certs | awk '/BEGIN/ { i++; } /BEGIN/, /END/ { print > "file-" i ".pem" }'

This will simply create a file for each object with a numerical filename. It doesn't differentiate between certificates and CRLs. If you need that, you could modify the search string so that it looks for BEGIN CERTIFICATE, END CERTIFICATE or BEGIN X509 CRL,END X509 CRL and change the "file-" and/or ".pem" to something appropriate in each case.


If you want to do this in Python, use the asn1crypto module:

import os
from asn1crypto import cms

with open( 'file.p7s', 'rb') as f:
    info = cms.ContentInfo.load(f.read())

signed_data = info['content']
certificates = signed_data['certificates']
crls = signed_data['crls']

# Certificate
for certificate in certificates:
    cn = certificate.native['tbs_certificate']['subject']['common_name']
    with open (cn+'.crt', 'wb') as f:
        f.write(certificate.dump())

# Note: I don't have a CMS file with CRLs, so the next section hasn't been tested.    
for crl in crls:
    cn = crl.native['tbs_cert_list']['issuer']['common_name']
    with open (cn+'.crl', 'wb') as f:
        f.write(crl.dump())