How to Programmatically Split Concatenated PEM Certificate Files Using AWK and CSplit


3 views

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