Skip to content

Instantly share code, notes, and snippets.

@wolever
Last active August 16, 2019 13:42
Show Gist options
  • Select an option

  • Save wolever/5762823 to your computer and use it in GitHub Desktop.

Select an option

Save wolever/5762823 to your computer and use it in GitHub Desktop.
Tools for creating an x509 certificate authority and using it to create and sign certificates.

SSL Helpers

These scripts can be used to generate different kinds of SSL keys and certificates.

Usage

  1. Create a certificate authority::

    $ ./mkca <ca_name> .............++++++ .....++++++ writing new private key to '<ca_name>/cakey.pem' -----

  2. Trust the CA's certificate, which will be stored at <ca_name>/cacert.crt. On Windows and Mac, this can be done by double clicking the file then adding it to the list of "Trusted Root Certification Authorities", or similar.

  3. Create an SSL certificate (where <cert_cn> will be the common name used on the certificate):

    $ ./mkcert <ca_name> <cert_cn>
    --- creating key ---
    Generating a 1024 bit RSA private key
    .........++++++
    ......++++++
    writing new private key to '<cert_cn>-temp-private.pem'
    -----
    Using configuration from ./openssl.cfg
    Check that the request matches the signature
    Signature ok
    The Subject's Distinguished Name is as follows
    commonName            :T61STRING:'<cert_cn>'
    Certificate is to be certified until Jun  3 17:21:15 2031 GMT (7300 days)
    Sign the certificate? [y/n]:y
    1 out of 1 certificate requests certified, commit? [y/n]y
    Write out database with 1 new entries
    Data Base Updated
    <ca_name>/certs/<cert_cn>.pem created.
    
  4. Use the dump_ssl script to verify that the certificate is correct::

    $ ./dump_ssl <ca_name>/certs/<cert_cn>.pem Private-Key: (1024 bit) modulus:

    00:b4:8c:01:20:52:a5:f1:11:d1:d1:52:bd:ec:7b: a6:12:d6:c6:5f:ef:ff:fc:bf:86:06:bc:51:be:8c: 30:6b:09:15:c0:de:ab:9a:b3:85:cc:1d:a1:63:b1:

    ... Certificate:

    Data:

    Version: 3 (0x2) Serial Number: 1 (0x1) Signature Algorithm: sha1WithRSAEncryption Issuer: CN=<ca_name> Validity

    Not Before: Jun 8 17:21:15 2011 GMT Not After : Jun 3 17:21:15 2031 GMT

    Subject: CN=<cert_cn> Subject Public Key Info:

    Public Key Algorithm: rsaEncryption RSA Public Key: (1024 bit)

    Modulus (1024 bit):

    00:b4:8c:01:20:52:a5:f1:11:d1:d1:52:bd:ec:7b: ... 01:b2:e3:37:12:0f:21:9e:bb

    Exponent: 65537 (0x10001)

    X509v3 extensions:
    X509v3 Basic Constraints:

    CA:FALSE

    X509v3 Subject Key Identifier:

    36:BA:81:45:68:E0:19:41:DC:7A:B0:A8:DE:8D:82:C1:46:41:8F:EE

    X509v3 Authority Key Identifier:

    keyid:AD:E7:D8:50:3E:A7:9D:26:D9:92:4D:44:46:D7:88:95:CF:CC:C1:3E DirName:/CN=<ca_name> serial:F0:3C:D7:80:54:DD:15:9B

    Signature Algorithm: sha1WithRSAEncryption

    11:33:24:56:32:72:0c:a8:b6:b4:5d:06:02:3e:7d:2f:82:67: ... 04:73

  5. Copy the new key and certificate (which has been signed by <ca_name>) into place:

    $ scp <ca_name>/certs/<cert_cn>.pem host:/etc/ssl/private/<cert_cn>.pem
    
#!/bin/bash
# from http://dv-zeuthen.desy.de/security/examples_for_usage_of_openssl_command/
openssl rsa -noout -text -in "$1" | head -n5
echo "..."
openssl x509 -noout -text -in "$1"
#!/bin/bash
set -e
nodes="-nodes"
if [[ "$1" == "-des" ]]; then
nodes=""
shift
fi
if [[ ! "$1" || ! "$2" || "$1" =~ "^-" ]]; then
echo "usage: $0 [-des] CommonName directory"
exit 2
fi
name="$1"
dir="$2"
subj="/C=CA/ST=Ontario/L=Toronto/O=Luminautics Inc./CN=$name"
cakey="ca.key"
if [[ ! "$nodes" ]]; then
cakey="$cakey-encrypted"
fi
if [[ -d "$dir" ]]; then
echo "error: $dir/ exists"
exit 1
fi
mkdir "$dir"
cat "`dirname "$0"`"/openssl.default.cfg | sed -e "s/{{CAKEY}}/$cakey/" > "$dir/openssl.cfg"
cd "$dir"
# Because we want to explicitly set the default start and end dates (see
# default_startdate, default_enddate in openssl.cfg), some hoops need to be
# jumped through:
# - A key + self-signed cert must be created
# - A CSR must be generated from that key
# - Then the self-signed cert must be used to sign the CSR
# First create a key + self-signed certificate
openssl req -new -x509 -config ./openssl.cfg \
-keyout "$cakey" \
-out "temp_cert.crt" \
-subj "$subj" \
$nodes \
-extensions "standard_ca"
mkdir "certs"
touch "database"
echo "0001" > "serial"
# Generate a new CSR from the private key
openssl req -new -config ./openssl.cfg \
-key "$cakey" \
-out "temp_csr.csr" \
-subj "$subj" \
$nodes \
-extensions "standard_ca"
# Use the self-signed certificate to sign the CSR, producing the final
# certificate.
openssl ca -config ./openssl.cfg \
-batch \
-cert "temp_cert.crt" \
-out "ca.crt" \
-in "temp_csr.csr" \
-extensions "standard_ca"
# Optionally, export the cert in pkcs12 format
openssl pkcs12 -export -in "$cakey" -out "ca.p12"
# Cleanup!
rm temp_*
#!/bin/bash
set -e
usage() {
echo "usage: $0 [-server] [-des] ca keyname"
echo " -server include 'nsCertType=server' in the certificate"
echo " (for use with OpenVPN's 'ns-cert-type' option)"
echo " -des also include an encrypted private key"
}
extensions="standard"
nodes="-nodes"
while :; do
if [[ $# -eq 2 ]]; then
break
fi
case "${1-}" in
"-server")
extensions="server"
shift
;;
"-des")
nodes=""
shift
;;
**)
usage
exit 2
;;
esac
done
ca="${1%/}"
keyname="$2"
subj="/C=CA/ST=Ontario/L=Toronto/CN=$keyname"
if [[ ! -d "$ca" ]]; then
echo "error: can't find $ca/"
exit 1
fi
cd "$ca/"
echo "--- creating key ---"
keyfile="$keyname-temp.key"
reqfile="$keyname-temp.csr"
crtfile="$keyname-temp.crt"
openssl req -new -config ./openssl.cfg \
-keyout "$keyfile" \
-out "$reqfile" \
-subj "$subj" \
-nodes \
-extensions "$extensions"
if [[ -f "passphrase" ]]; then
echo "=========="
echo "PASSWORD: `cat passphrase`"
echo "=========="
fi
openssl ca -config ./openssl.cfg \
-batch \
-noemailDN \
-in "$reqfile" \
-out "$crtfile" \
-extensions "$extensions"
pemfile="certs/$keyname.pem"
if [[ "$nodes" ]]; then
cat "$crtfile" "$keyfile" > "$pemfile"
echo "$ca/$pemfile created."
else
# Store an encrypted copy of the certificate in the CA's store
openssl rsa '-in' "$keyfile" -des3 -out "$keyfile-encrypted"
cat "$crtfile" "$keyfile-encrypted" > "$pemfile-encrypted"
echo "$ca/$pemfile-encrypted created."
# And stick an unencrypted copy of the certificate in /tmp/
touch "/tmp/$keyname.pem"
chmod 600 "/tmp/$keyname.pem"
cat "$crtfile" "$keyfile" > "/tmp/$keyname.pem"
echo "/tmp/$keyname.pem created"
fi
rm "$keyname-temp"*
#
# OpenSSL configuration file.
#
# Establish working directory.
dir = .
[ ca ]
default_ca = CA_default
[ CA_default ]
serial = $dir/serial
database = $dir/database
new_certs_dir = $dir/certs
certificate = $dir/ca.crt
private_key = $dir/{{CAKEY}}
default_md = sha1
preserve = no
nameopt = default_ca
certopt = default_ca
policy = policy_match
default_days =
default_startdate = 700101000001Z
default_enddate = 300101000000Z
[ policy_match ]
countryName = optional
stateOrProvinceName = optional
localityName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
[ req ]
default_bits = 1024 # Size of keys
default_keyfile = key.pem # name of generated keys
default_md = sha1 # message digest algorithm
string_mask = nombstr # permitted characters
distinguished_name = req_distinguished_name
[ req_distinguished_name ]
#0.organizationName = Organization Name (company)
#organizationalUnitName = Organizational Unit Name (department, division)
#emailAddress = Email Address
#emailAddress_max = 40
#localityName = Locality Name (city, district)
#stateOrProvinceName = State or Province Name (full name)
#countryName = Country Name (2 letter code)
#countryName_min = 2
#countryName_max = 2
#commonName = commonName (hostname)
#commonName_max = 64
#0.organizationName_default = David Wolever
#organizationalUnitName_defaul =
#emailAddress_default = david@wolever.net
#localityName_default = Toronto
#stateOrProvinceName_default = Ontario
#countryName_default = CA
#
# Custom extension definitions
#
[ standard_ca ]
basicConstraints = CA:TRUE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always
[ standard ]
basicConstraints = CA:FALSE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer:always
[ server ]
basicConstraints = CA:FALSE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer:always
nsCertType = server
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment