SSL Client Certificates - shawfdong/hyades GitHub Wiki
We use layered security for maia.ucsc.edu. Here we describe how we secure the site with SSL Client Certificates.
NOTE all major web browser vendors have made announcements about depreciating support for SHA1 in browsers and moving to SHA256. This guide is updated to use SHA256 (SHA2).
$ umask 0077 $ mkdir CA $ cd CA $ mkdir certs crl newcerts private $ touch index.txt $ echo 01 > serial $ echo 01 > crlnumber
The stock openssl.cnf is a good starting point. Here is my ca.cnf (placed in the CA directory created above):
[ ca ] default_ca = CA_default # The default ca section [ CA_default ] dir = . # Where everything is kept certs = $dir/certs # Where the issued certs are kept crl_dir = $dir/crl # Where the issued crl are kept database = $dir/index.txt # database index file. unique_subject = no # Set to 'no' to allow creation of # several certificates with same subject. new_certs_dir = $dir/newcerts # default place for new certs. certificate = $dir/dong-root-ca.crt # The CA certificate serial = $dir/serial # The current serial number crlnumber = $dir/crlnumber # the current crl number # must be commented out to leave a V1 CRL crl = $dir/crl.pem # The current CRL private_key = $dir/private/dong-root-ca.key # The private key RANDFILE = $dir/private/.rand # private random number file x509_extensions = usr_cert # The extentions to add to the cert name_opt = ca_default # Subject Name options cert_opt = ca_default # Certificate field options default_days = 1095 # how long to certify for default_crl_days= 1095 # how long before next CRL default_md = sha256 # use public key default MD preserve = no # keep passed DN ordering policy = policy_match # For the CA policy [ policy_match ] countryName = match stateOrProvinceName = match organizationName = optional organizationalUnitName = optional commonName = supplied emailAddress = optional #################################################################### [ req ] default_bits = 2048 default_keyfile = privkey.pem distinguished_name = req_distinguished_name attributes = req_attributes x509_extensions = v3_ca # The extentions to add to the self signed cert string_mask = utf8only #################################################################### [ req_distinguished_name ] countryName = Country Name (2 letter code) countryName_default = US countryName_min = 2 countryName_max = 2 stateOrProvinceName = State or Province Name (full name) stateOrProvinceName_default = California localityName = Locality Name (eg, city) localityName_default = Santa Cruz commonName = Common Name (e.g. server FQDN or YOUR name) commonName_max = 64 emailAddress = Email Address emailAddress_max = 64 #################################################################### [ req_attributes ] challengePassword = A challenge password challengePassword_min = 4 challengePassword_max = 20 #################################################################### [ usr_cert ] # These extensions are added when 'ca' signs a request. basicConstraints=CA:FALSE nsComment = "OpenSSL Generated Certificate" subjectKeyIdentifier=hash authorityKeyIdentifier=keyid,issuer #################################################################### [ v3_req ] # Extensions to add to a certificate request basicConstraints = CA:FALSE keyUsage = nonRepudiation, digitalSignature, keyEncipherment #################################################################### [ v3_ca ] # Extensions for a typical CA subjectKeyIdentifier=hash authorityKeyIdentifier=keyid:always,issuer basicConstraints = CA:true #################################################################### [ crl_ext ] # CRL extensions. authorityKeyIdentifier=keyid:always
Create a bash script (ca.sh) in the CA directory:
#!/bin/bash ### CA umask 0077 base=dong-root-ca openssl req \ -x509 -new -days 3650 -newkey rsa:2048 -sha256 \ -subj "/C=US/ST=California/L=Santa Cruz/CN=Frank Dong ROOT CA" \ -keyout private/$base.key -out $base.crt -config ca.cnf openssl x509 -in $base.crt -noout -text
then run:
$ ./ca.shwhich will produce 2 files: dong-root-ca.crt (the root certificate) and private/dong-root-ca.key (the private key).
Generate a CSR (Certificate Signing Request) using the following bash script (req.sh):
#!/bin/bash ### certificate request umask 0077 if [ $# -ne 1 ] then echo "Usage: $0 name" exit 1 fi openssl req \ -new -newkey rsa:2048 -sha256 -config ca.cnf \ -keyout private/$1.key -out $1.csr openssl req -in $1.csr -noout -text
For example:
$ ./req.sh dong01
Then sign the CSR using the following bash script (sign.sh)
#!/bin/bash ### to sign a certificate request umask 0077 if [ $# -ne 1 ] then echo "Usage: $0 name" exit 1 fi openssl ca -config ca.cnf \ -in $1.csr -out certs/$1.crt
For example:
$ ./sign.sh dong01
For the client certificate to be used in a web browser, e.g., Firefox, it must to be exported to the PKCS #12 format. We use the following bash script (export.sh):
#!/bin/bash ### package the key and cert in a PKCS12 file umask 0077 if [ $# -ne 1 ] then echo "Usage: $0 name" exit 1 fi openssl pkcs12 -export \ -in certs/$1.crt -inkey private/$1.key -out $1.p12
For example:
$ ./export.sh dong01
It will produce dong01.p12 (the PKCS#12 certificate), which can then be imported by Firefox.
We use the following bash script (crl.sh) to generate a Certificate Revocation List:
#!/bin/bash ### create CRL umask 0077 openssl ca -config ca.cnf -gencrl -out crl.pem # binary format openssl crl -inform PEM -in crl.pem -outform DER -out crl.der openssl crl -in crl.pem -text
For example:
$ ./crl.shwhile will produce crl.pem (the CRL file). Although the Certificate Revocation List is empty at this stage, the file is still required by nginx.
In case a client certificate is stolen or compromised, we can revoke it with the following bash script (revoke.sh):
#!/bin/bash ## revoke a certificate == umask 0077 if [ $# -ne 1 ] then echo "Usage: $0 name" exit 1 fi openssl ca -config ca.cnf -revoke certs/$1.crt ### update the CRL openssl ca -config ca.cnf -gencrl -out crl.pem # binary format openssl crl -inform PEM -in crl.pem -outform DER -out crl.der openssl crl -in crl.pem -text
For example:
$ ./revoke.sh dong01
Upload both crl.pem (the CRL file) and dong-root-ca.crt (the root certificate) to the directory /etc/ssl/ on the web server. Add the following lines to the configuration file of nginx (e.g., /etc/nginx/conf.d/maia.conf):
ssl_client_certificate /etc/ssl/dong-root-ca.crt; ssl_crl /etc/ssl/crl.pem; ssl_verify_client on;