When working with SSL/TLS configurations (particularly in Apache/mod_ssl environments), you'll often encounter concatenated PEM files containing multiple certificates. These are commonly used in SSLCACertificateFile
directives and PKCS#7 output from OpenSSL.
For robust processing in shell scripts, AWK provides excellent pattern matching capabilities:
cat combined.pem | awk 'split_after==1{n++;split_after=0}
/-----END CERTIFICATE-----/ {split_after=1}
{if(length($0) > 0) print > "cert" n ".pem"}'
Key improvements over basic solutions:
- Handles blank lines (common in OpenSSL output)
- Maintains proper certificate boundaries
- Generates sequentially numbered output files (cert1.pem, cert2.pem, etc.)
For simpler cases where certificates are properly delimited:
csplit -f cert- combined.pem '/-----BEGIN CERTIFICATE-----/' '{*}'
This approach creates files prefixed with "cert-" followed by sequential numbers.
1. Processing OpenSSL PKCS#7 output:
openssl pkcs7 -in chain.p7b -outform PEM -print_certs | \
awk '/-----BEGIN CERTIFICATE-----/{n++}
{print > "cert" n ".pem"}'
2. Validating certificate chains:
for cert in $(ls cert*.pem); do
openssl x509 -in $cert -noout -subject
done
Method | Pros | Cons |
---|---|---|
AWK | Handles malformed files better | More complex syntax |
CSplit | Cleaner output filenames | Requires standard delimiters |
The solutions above handle most scenarios, but watch for:
- Mixed certificate/private key files
- Non-standard line endings
- Certificate chains with comments
For these cases, consider pre-processing with sed
or using OpenSSL's text
output option for inspection.
When working with Apache's SSLCACertificateFile
or OpenSSL PKCS7 outputs, you often encounter PEM files containing multiple certificates concatenated together. These files follow the pattern:
-----BEGIN CERTIFICATE-----
[Base64-encoded data]
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
[Base64-encoded data]
-----END CERTIFICATE-----
For precise control over certificate splitting, this AWK one-liner handles edge cases:
cat combined.pem | awk 'split_after==1{n++;split_after=0}
/-----END CERTIFICATE-----/ {split_after=1}
{if(length($0) > 0) print > "cert" n ".pem"}'
Key improvements over basic solutions:
- Handles empty lines (common in OpenSSL outputs)
- Generates sequential filenames (cert1.pem, cert2.pem)
- Maintains original PEM formatting
For systems with GNU coreutils, csplit
offers a clearer syntax:
csplit -f cert- combined.pem '/-----BEGIN CERTIFICATE-----/' '{*}'
This creates files named cert-00, cert-01, etc. Note that:
- The first file may contain preamble text (add
--suppress-matched
to remove) - Requires GNU csplit (available on most Linux distros)
Handling OpenSSL PKCS7 output:
openssl pkcs7 -outform PEM -in chain.p7b -print_certs | \
awk '/-----BEGIN/,/-----END/ {if(length($0) > 0) print > "cert" ++n ".pem"}'
Batch processing multiple files:
for file in *.pem; do
csplit -f "${file%.*}-" "$file" '/-----BEGIN/' '{*}'
done
After splitting, verify each certificate:
for cert in cert-*; do
openssl x509 -in "$cert" -noout -text && echo "$cert: Valid"
done