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