Generate certificate pins for your apps.
Created
November 28, 2020 06:22
-
-
Save kousu/d3fd6e32c66f89914995d113b0a3a850 to your computer and use it in GitHub Desktop.
http cert pinning
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
# pin.sh | |
set -eo pipefail | |
if [ -z "$1" ]; then | |
cat <<DOCS | |
usage: pin.sh CERT.pem [CERT.pem ...] | |
Create x509 certificate pins for use with libraries like OkHttp (https://square.github.io/okhttp/4.x/okhttp/okhttp3/-certificate-pinner/) | |
Only supports sha256 pins. Some implementations support sha1, but that is always the weaker choice, cryptography-wise. | |
References: | |
https://tools.ietf.org/html/rfc7469 | |
https://www.imperialviolet.org/2011/05/04/pinning.html | |
https://serverfault.com/questions/911823/how-to-extract-public-key-from-a-der-file-in-subjectpublickeyinfo-format | |
example: | |
$ openssl s_client -showcerts -connect google.com:443 </dev/null > google.pem | |
depth=1 C = US, O = Google Trust Services, CN = GTS CA 1O1 | |
verify return:1 | |
depth=0 C = US, ST = California, L = Mountain View, O = Google LLC, CN = *.google.com | |
verify return:1 | |
DONE | |
$ ./pin.sh google.pem | |
sha256/XL7jJ71nBgDA7ya7f7ty0JCgcuoMzHOLAl9t8SnrjFY= | |
DOCS | |
exit 1; | |
fi | |
pin() { | |
CERT="$1" | |
# openssl is cranky and difficult; for a not-too-untrue summary of the situation: http://mirrors.dotsrc.org/fosdem/2014/Janson/Sunday/NSA_operation_ORCHESTRA_Annual_Status_Report.webm | |
# nevertheless, it is fast and pretty well tested, so let me explain what is happening here. | |
# 1. There are two possible input formats: a certificate in .pem format and a certificate in .der format. | |
# since we don't know which, try them both | |
# 1b. -noout doesn't mean "no out", it means "disable the normal default output"; -pubkey causes a second, unrelated, piece of output to come out. | |
if HASH=$((openssl x509 -in "$CERT" -inform pem -pubkey -noout || | |
openssl x509 -in "$CERT" -inform der -pubkey -noout) 2>/dev/null | | |
# the -pubkey format is always pem, but we need der, so convert it | |
openssl enc -base64 -d | | |
# now hash it | |
openssl dgst -sha256 -binary | | |
# and make it binary safe | |
openssl enc -base64; ); then | |
echo "sha256/$HASH" | |
else | |
echo "$CERT couldn't be hashed. Is it in the right format?" >&2 | |
exit 1 | |
fi | |
} | |
while [ -n "$1" ]; do | |
pin "$1" | |
shift | |
done |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
🦁