Skip to content

Instantly share code, notes, and snippets.

@JonTheNiceGuy
Created May 5, 2023 16:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JonTheNiceGuy/7929f15b86d6171b00984f8eb6bf35c0 to your computer and use it in GitHub Desktop.
Save JonTheNiceGuy/7929f15b86d6171b00984f8eb6bf35c0 to your computer and use it in GitHub Desktop.
A bash script which gets the certificate SHA256 hashes of certificates in a chain, or for an individual certificate
#!/bin/bash
set -Eeuo pipefail
trap cleanup SIGINT SIGTERM ERR EXIT
cleanup() {
trap - SIGINT SIGTERM ERR EXIT
if [ -z "${KEEP:-}" ] && [ -n "${tempdir:-}" ]
then
rm -Rf "$tempdir"
fi
}
fail() {
stderr "FAIL: $1"
exit $2
}
stderr() {
echo "$1" >&2
}
debug() {
if [ -n "${DEBUG:-}" ]
then
stderr "DBUG: $1"
fi
}
info() {
if [ -n "${DEBUG:-}" ] || [ -n "${INFO:-}" ]
then
stderr "INFO: $1"
fi
}
warning() {
stderr "WARN: $1"
}
log() {
stderr "LOG : $1"
}
usage() {
stderr "Need to provide the domain name you want the certificate pinning statements for, or a single PEM file."
exit 1
}
get_sha256_base64() {
openssl x509 -in "$1" -outform der | openssl dgst -sha256 -binary | base64
}
get_CN() {
echo "$1" | sed -e 's/^.*CN = //'
}
get_subject() {
get_CN "$(openssl x509 -in "$1" -text | grep "Subject:")"
}
get_issuer() {
get_CN "$(openssl x509 -in "$1" -text | grep "Issuer:")"
}
get_validity_dates_from() {
openssl x509 -in "$1" -text | grep -iA2 "Validity" | grep "Not Before" | sed -e 's/^.*: //'
}
get_validity_dates_to() {
openssl x509 -in "$1" -text | grep -iA2 "Validity" | grep "Not After" | sed -e 's/^.*: //'
}
get_data() {
echo "/**"
echo " * $(get_subject "$1")"
echo " * Verified by: $(get_issuer "$1")"
echo " * Valid from: $(get_validity_dates_from "$1")"
echo " * Expires: $(get_validity_dates_to "$1")"
echo " */"
echo "const val PIN = \"sha256/$(get_sha256_base64 "$1")\""
}
if [ -z "${1:-}" ]
then
usage
elif [[ "$1" =~ .*\.pem$ ]]
then
get_data "$1"
else
tempdir="$(mktemp -d)"
debug "Temporary directory is $tempdir"
log "Connecting for certificate chain"
openssl s_client -showcerts -servername "$1" -connect "$1:443" <<< "Q" > "${tempdir}/chain.txt" 2>/dev/null || fail "Connection failed" 1
log "Chain received"
log "Getting individual certificates from the chain"
unset CERT_ON
while read -r line
do
if [[ $line =~ .*\ s:.* ]]
then
debug "Found CN Line: $line"
pos="$(echo "$line" | cut -ds -f1 | sed -e 's/ //g')"
cn="$(echo "$line" | sed -e 's/.*CN = //')"
debug "Found CN: $cn"
fi
if [ -n "${CERT_ON:-}" ]
then
if [[ $line =~ -----END\ CERTIFICATE----- ]]
then
unset CERT_ON
debug "Found the end of the cert for $cn"
fi
echo "$line" >> "${tempdir}/${pos}.${cn}.pem"
else
if [[ $line =~ -----BEGIN\ CERTIFICATE----- ]]
then
CERT_ON=1
debug "Found the start of the cert for $cn"
echo "$line" > "${tempdir}/${pos}.${cn}.pem"
fi
fi
done < "${tempdir}/chain.txt"
find "${tempdir}" -name \*.pem | sort | while read -r file
do
get_data "$file"
done
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment