Skip to content

Instantly share code, notes, and snippets.

@kousu
Created February 21, 2016 06:52
Show Gist options
  • Select an option

  • Save kousu/5c0b7a959885cdade8ea to your computer and use it in GitHub Desktop.

Select an option

Save kousu/5c0b7a959885cdade8ea to your computer and use it in GitHub Desktop.
openssl sucks
#!/bin/sh
#
# generates a self-signed CA and certificates signed by that CA.
# If you install the CA into your certificate stores (in Firefox: Prefs->Advanced->Certs->Import, in Gnome: open the .crt in and whose .crt,.key pair can be used
# worked out with http://www.akadia.com/services/ssh_test_certificate.html and trial and error
# (as usual, with OpenSSL)
# Usage:
# ./mkcert # and follow the prompts, to make a CA
# ./mkcert my.domain.name
# ./mkcert 4chan.tk
# Find CA.crt and import it to your browser/OS cert stores.
# For extra security, once you are done generating certs, *delete* CA.key. Then it cannot sign any more keys, but its signature can still be checked, via the magic of Public Key Crypto
# For each domain, any server you run will need to be given the pair (domain.crt, domain.key). domain.crt is public knowledge, but hold domain.key safe (though the attack surface is faiiiiiirly small, since your self-signed CA won't exist except your own devices)
# e.g. in python:
# ```
# httpd = http.server(('0.0.0.0',443), http.server.SimpleHTTPRequestHandler)
# import ssl
# ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2);
# ssl.load_cert_chain("domain.crt", "domain.key"); #here you have to pass *both* files
# httpd.socket = ssl.wrap_socket(httpd.socket);
# httpd.serve_forever();
# ```
#
# e.g. in apache.conf:
# ```
# SSLEngine on
# SSLCertificateFile domain.crt
# SSLCertificateKeyFile domain.key
# ```
TARGET=$1
case $TARGET in
"")
DAYS=${2:-90} #CAs are good for 3 months by default
echo
echo "Generating self-signed certificate authority (CA)."
echo "--------------------------------------------------"
echo
echo "You will be asked to fill in details which should identify your new certificate authority."
echo "Luckily, no one ever looks at their cert stores so you can type anything you like."
echo "The only field that really matters is common name (CN)."
echo
echo "If you do not wish to lose your previous CA, quit now."
echo
echo "Your CA will be good for $DAYS days."
read -p "[press enter] "
echo
rm CA.key CA.crt 2>/dev/null
openssl genrsa -out CA.key 4096 && #there's also -newkey rsa:4096 as an option to req, but a) it doesn't let us pick the name b) it doesn't let us make an unencrypted key
#openssl req -new -key CA.key -out CA.csr -extensions v3_ca &&
#openssl x509 -req -in CA.csr -out CA.crt -signkey CA.key -extensions v3_ca -days "$DAYS" && #NOTE! -signkey, despite its name sounding like giving the key to sign with, actually is how we *cause* self-signed;
# also for some reason in this form -extensions is ignored. motherfucker.
openssl req -new -x509 -days "$DAYS" -key CA.key -out CA.crt -extensions v3_ca &&
#fd:4 4< <(read -p "Enter Password: " A; echo $A) && #<-- if openssl fails it doesn't return non-zero. great.
# TODO: give the /option/ of encrypting the key; there's a way to do this with 'openssl rsa'
# I believe if you inline the genrsa command (by using -newkey instead of -key) you are not given the option to skip putting a password on
#
echo 'CA.crt generated. Try `openssl x509 -in CA.crt -text` to see results'
echo 'Under *nix, you may install your CA as an OS-level CA by (as root):'
echo '\# cp CA.crt /etc/ssl/certs/my_new_ca_name.pem && c_rehash'
echo 'You may also install it into Firefox/Chrome using their preferences GUIs'
echo 'or into Windows by using the Control Panel'
# headsup:
# so *this* command works in one go:
# openssl req -new -x509 -days 3650 -extensions v3_ca -keyout cakey.pem -out cacert.pem -batch -passout pass:password
# but it requires a password, which is annoying
# there's also `openssl ca` and `/etc/ssl/misc/CA.sh` but oh god no
;;
*)
DAYS=${2:-3} # keys are only good for 3 days by default
echo
echo "Generating $1.crt and $1.key, signed by the CA."
echo
echo "If you do not wish to overwrite your previous cert, quit now."
echo
echo "Your cert will be good for $DAYS days."
echo "-----------------------------------------------"
read -p "[press enter] "
echo
rm "$1.key" "$1.crt" 2>/dev/null
openssl genrsa -out "$1".key 4096 &&
openssl req -new -key "$1".key -out "$1".csr -subj "/CN=$1" &&
# wtf is CA.srl for? why can we only create it when we're signing a sub-certificate??
openssl x509 -req -in "$1".csr -out "$1".crt -CA CA.crt -CAkey CA.key -CAcreateserial -days "$DAYS" &&
rm "$1".csr
echo $1'.crt generated. Try `openssl x509 -in '$1'.crt -text` to see results'
;;
esac
echo
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment