#!/bin/bash # Clean up a x509 cert to make it nice to use # supports multiple certs in the same file! # # Copyright 2014-2023 Robin H Johnson # Licensed under the BSD-3 license # http://opensource.org/licenses/BSD-3-Clause TMP=$(mktemp) TMPD=$(mktemp -d) TMPOUT=$(mktemp) #set -x # shellcheck disable=SC2064 trap "rm -rf $TMP $TMPD $TMPOUT" SIGINT SIGTERM [ ${#@} -eq 0 ] && set -- - n=0 for f1 in "$@" ; do n=$((n + 1)) test -f "$f1" || continue # Remove trailing space <"$f1" tr -d '\r' | sed 's,[[:space:]]*$,,g' -r >"${TMP}" # To be valid, a PEM block MUST be a newline or EOF to close the END. # But some systems truncate it; so fix up first. # "---END ...---\n" sed -i -r -e 's/^((---+)END [A-Z0-9_,; ]+\2+)(.*?)$/\1\n\3/g' "${TMP}" PREFIX=$(printf 'x509-expand-input-f%05d-p' $n) if ! ( cd "$TMPD" && csplit -s --elide-empty-files -n 3 --prefix "${PREFIX}" "${TMP}" /^-----BEGIN/ '{*}' ); then echo "Failed to split: $f1" 1>&2 continue fi truncate -s 0 "${TMPOUT}" files=$(find "$TMPD" -name "${PREFIX}*" -type f |sort ) [ "$f1" != "-" ] && exec 5>&1 >"${TMPOUT}" for f2 in $files ; do #echo === $f if false ; then : elif grep -sq -e '- *BEGIN CERTIFICATE REQUEST *-' "$f2"; then # Match request before Cert, for longest substring line0=$(grep -m1 -e '- *BEGIN CERTIFICATE REQUEST' "$f2") line1=${line0/BEGIN /END } sed -n -e "/^${line0}$/,/^${line1}$/p" <"$f2" openssl req -in "$f2" -noout -text -reqopt ext_default,ext_parse,ext_dump -modulus |sed 's,[[:space:]]*$,,g' elif grep -sq -e '- *BEGIN CERTIFICATE *-' "$f2"; then line0=$(grep -m1 -e '- *BEGIN CERTIFICATE *-' "$f2") line1=${line0/BEGIN /END } sed -n -e "/^${line0}$/,/^${line1}$/p" <"$f2" openssl x509 -in "$f2" -noout -text -certopt ext_default,ext_parse,ext_dump |sed 's,[[:space:]]*$,,g' # make it easier to search our certificates in the repo with all forms of certificate identifiers: # hex strings with and without colons # for uppercase/lowercase, use the -i of your search tooling. # # print a version of the fingerprints with and without colons for d in -md5 -sha1 -sha256 -sha512 ; do openssl x509 -in "$f2" -noout $d -fingerprint |sed 's,[[:space:]]*$,,g; p; s/://g;' done # the serial here has colons; for x in -serial -subject -subject_hash -issuer -issuer_hash -dates -modulus ; do [ "${x/_hash}" != "$x" ] && echo -n "${x/-/}=" openssl x509 -in "$f2" -noout $x |sed 's,[[:space:]]*$,,g' # print a version of the serial with colons [ "${x/-serial}" != "$x" ] && openssl x509 -in "$f2" -noout $x |sed 's,[[:space:]]*$,,g' | sed 's,^serial=,,g' | perl -lne 'print "serial=", join(":", grep $_, split/(..)/,lc $_)' done # Now the dates openssl x509 -startdate -in "$f2" -noout |cut -d= -f2- |tr '\n' '\0' | xargs -0 -n1 date +notBeforeEpoch=%s -d openssl x509 -enddate -in "$f2" -noout |cut -d= -f2- |tr '\n' '\0' | xargs -0 -n1 date +notAfterEpoch=%s -d #cat $files elif grep -sq -e '- *BEGIN PUBLIC KEY' "$f2"; then line0=$(grep -m1 -e '- *BEGIN PUBLIC KEY' "$f2") line1=${line0/BEGIN /END } sed -n -e "/^${line0}$/,/^${line1}$/p" <"$f2" openssl rsa -pubin -in "$f2" -noout -text -modulus elif grep -sq -e '- *BEGIN RSA PRIVATE KEY' -e '- *BEGIN PRIVATE KEY' "$f2"; then line0=$(grep -m1 -e '- *BEGIN RSA PRIVATE KEY' -e '- *BEGIN PRIVATE KEY' "$f2") line1=${line0/BEGIN /END } sed -n -e "/^${line0}$/,/^${line1}$/p" <"$f2" if grep -sq 'Proc-Type: 4,ENCRYPTED' "$f2"; then echo "# Cannot show encrypted key" else openssl rsa -in "$f2" -noout -text -modulus fi elif grep -sq -e '- *BEGIN DH PARAM' "$f2"; then line0=$(grep -m1 -e '- *BEGIN DH PARAM' "$f2") line1=${line0/BEGIN /END } sed -n -e "/^${line0}$/,/^${line1}$/p" <"$f2" openssl dhparam -in "$f2" -noout -text elif grep -sq -e '- *BEGIN DSA PARAM' "$f2"; then line0=$(grep -m1 -e '- *BEGIN DSA PARAM' "$f2") line1=${line0/BEGIN /END } sed -n -e "/^${line0}$/,/^${line1}$/p" <"$f2" openssl dsaparam -in "$f2" -noout -text elif grep -sq -e '- *BEGIN DSA PRIVATE' "$f2"; then line0=$(grep -m1 -e '- *BEGIN DSA PRIVATE' "$f2") line1=${line0/BEGIN /END } sed -n -e "/^${line0}$/,/^${line1}$/p" <"$f2" if grep -sq 'Proc-Type: 4,ENCRYPTED' "$f2"; then echo "# Cannot show encrypted key" else openssl dsa -in "$f2" -noout -text -modulus fi elif true ; then # Nuke content unless it's a comment starting with '^#' grep -e '^#' "$f2" : fi done if [ "$f1" != "-" ]; then exec 1>&5 chmod --reference "$f1" "$TMPOUT" || true chown --reference "$f1" "$TMPOUT" || true mv -f "$TMPOUT" "$f1" fi # shellcheck disable=SC2086 rm -f $files done