SSL/TLS-certificates for lazy people
In a nutshell, the SSL/TLS certificate (SSL: Secure Sockets Layer, TLS: Transport Layer Security) is a unique digital signature for the secure connection between the client and the server.
Creating SSL certificate can be divided into the following steps:
- create a personal key (Private Key);
- create a query to retrieve the certificate (Certificate Signing Request);
- creating a self-signed (Self-Signed Certificate).
To create the certificates I have written a small shell-script:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 |
#!/bin/sh #-------------------------------------------------------------------------- # certroutine.sh: script for creating SSL Certificates # $Revision: 1.00 (CentOS Edition by Wakko Warner) $ # $Comment: Any comments please send to wakko@acmelabs.spb.ru $ #-------------------------------------------------------------------------- ################# # User Settings # ################# # Country Name (2 letter code) C_="RU" # State or Province Name (full name) ST_="North-West" # Locality Name (eg, city) L_="Saint-Petersburg" # Organizational Name (eg, company) O_="" # Organizational Unit Name (eg, section) OU_="" # Common Name (eg, YOUR name, domain or host name, don't add *. for wildcards) CN_="" # Email Address EM_="" # Subject Alternative Names (enter * for wildcard certificate) SAN_="" [ "$C" == "" ] && C="$C_"; [ "$ST" == "" ] && ST="$ST_"; [ "$L" == "" ] && L="$L_" [ "$O" == "" ] && O="$O_"; [ "$OU" == "" ] && OU="$OU_"; [ "$CN" == "" ] && CN="$CN_" [ "$EM" == "" ] && EM="$EM_"; [ "$SAN" == "" ] && SAN="$SAN_" if [ "$CN" == "" ]; then echo "This script allows you to create:" echo " o public/private key pairs" echo " o SSL certificate signing requests (CSRs)" echo " o self-signed SSL certificates" echo echo "Edit settings in the script before beginning!" exit 0 fi OPENSSL=/usr/bin/openssl UTF8=`locale -c LC_CTYPE -k | grep -q charmap.*UTF-8 && echo -utf8` KEYLEN=2048 TYPE=rsa:${KEYLEN} [ "$SERIAL" == "" ] && SERIAL=0 [ "$DAYS" == "" ] && DAYS=365 TLSROOT=/etc/pki/tls KEY=${TLSROOT}/private/$CN.key CSR=${TLSROOT}/certs/$CN.csr CRT=${TLSROOT}/certs/$CN.crt PEM=${TLSROOT}/certs/$CN.pem if [ "$SAN" == "*" ]; then CN="*.$CN" SAN="" fi createconfig() { CNF=`/bin/mktemp /tmp/openssl.XXXXXX` CONFIG="-batch -config $CNF" cat <<EOF >$CNF [req] default_bits = $KEYLEN default_md = sha256 distinguished_name = req_distinguished_name req_extensions = v3_req [req_distinguished_name] countryName = Country Name (2 letter code) countryName_default = $C stateOrProvinceName = State or Province Name (full name) stateOrProvinceName_default = $ST localityName = Locality Name (eg, city) localityName_default = $L organizationName = Organizational Name (eg, company) organizationName_default = $O organizationalUnitName = Organizational Unit Name (eg, section) organizationalUnitName_default = $OU commonName = Common Name (eg, YOUR name) commonName_default = $CN commonName_max = 64 emailAddress = Email Address emailAddress_default = $EM [v3_ca] basicConstraints = CA:TRUE subjectKeyIdentifier = hash authorityKeyIdentifier = keyid:always,issuer:always [v3_req] basicConstraints = CA:FALSE keyUsage = nonRepudiation, digitalSignature, keyEncipherment EOF if [ ! "$SAN" == "" ]; then echo "subjectAltName = @alt_names" >>$CNF echo "" >>$CNF echo "[alt_names]" >>$CNF i=0 for AN in $SAN do ((i++)) echo "DNS.$i = $AN" >>$CNF done fi } usage() { echo "This script allows you to create:" echo " o public/private key pairs" echo " o SSL certificate signing requests (CSRs)" echo " o self-signed SSL certificates" echo echo Usage: echo " To create a KEY file, run \"$0 genkey\";" echo " To create a CSR file, run \"$0 gencsr\";" echo " To create a CRT file, run \"$0 gencrt\";" echo " To create a PEM file, run \"$0 genpem\";" echo " To verify a CSR file, run \"$0 verifycsr\";" echo " To verify a CRT file, run \"$0 verifycrt\"." echo echo "${TLSROOT}/private/ is output directory for key files" echo "${TLSROOT}/certs/ is output directory for CSR, CRT and PEM files" echo echo "To create a test certificate with serial number other than zero, add SERIAL=num" echo "You can also specify key length with KEYLEN=n and expiration in days with DAYS=n" echo "Also you can specify C=, ST=, L=, O=, OU=, CN=, EM=, SAN=..." echo echo Examples: echo " CN=www.example.com $0 genkey" echo " CN=www.example.com SAN=\"mail.example.com blog.example.com\" $0 gencsr" echo " CN=www.example.com SAN=\"mail.example.com blog.example.com\" $0 gencrt" return 0 } genkey() { umask 77 $OPENSSL genrsa $KEYLEN -sha256 -nodes >$KEY return 0 } gencsr() { umask 77 [ ! -f $KEY ] && genkey createconfig $OPENSSL req $UTF8 -new -key $KEY -out $CSR $CONFIG rm -f $CNF return 0 } verifycsr() { $OPENSSL req -in $CSR -text -verify -noout return 0 } gencrt() { umask 77 [ ! -f $KEY ] && genkey createconfig $OPENSSL req $UTF8 -new -key $KEY -x509 -days $DAYS -out $CRT $CONFIG -set_serial $SERIAL rm -f $CNF CRTHASH=`openssl x509 -hash -noout -in $CRT`.0 rm -f ${TLSROOT}/certs/$CRTHASH ln -s $CN.crt ${TLSROOT}/certs/$CRTHASH return 0 } verifycrt() { $OPENSSL verify $CRT return 0 } genpem() { umask 77 PEM1=`/bin/mktemp /tmp/openssl.XXXXXX` PEM2=`/bin/mktemp /tmp/openssl.XXXXXX` createconfig $OPENSSL req $UTF8 -newkey $TYPE -keyout $PEM1 -nodes -x509 -days $DAYS -out $PEM2 \ $CONFIG -set_serial $SERIAL rm -f $CNF cat $PEM1 > $PEM echo "" >> $PEM cat $PEM2 >> $PEM rm -f $PEM1 $PEM2 return 0 } case $1 in genkey | gencsr | gencrt | genpem | verifycsr | verifycrt) $1 exit $? ;; *) usage exit $? ;; esac |
At the top of the script, you can fill in the default values:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
# Country Name (2 letter code) C_="RU" # State or Province Name (full name) ST_="North-West" # Locality Name (eg, city) L_="Saint-Petersburg" # Organizational Name (eg, company) O_="Example Organization" # Organizational Unit Name (eg, section) OU_="" # Common Name (eg, YOUR name, domain or host name, don't add *. for wildcards) CN_="www.example.com" # Email Address EM_="hostmaster@example.com" # Subject Alternative Names (enter * for wildcard certificate) SAN_="mail.example.com" |
Then to create the key and self-signed certificate, you will need to perform:
1 2 3 4 5 6 7 8 |
$ ./certroutine.sh genkey Generating RSA private key, 2048 bit long modulus ............................................+++ .....................................+++ e is 65537 (0x10001) $ ./certroutine.sh gencrt $ ./certroutine.sh verifycrt /etc/pki/tls/certs/www.example.com.crt: OK |
The first command creates a private key /etc/pki/tls/private/www.example.com.key
, the second command creates a self-signed certificate /etc/pki/tls/certs/www.example.com.crt
, and a third team will check the validity of this certificate.
Note: Regardless of the script, if any certificate is written something like:
1 2 3 |
/etc/pki/tls/certs/www.example.com.crt: C = RU, ST = North-West, L = Saint-Petersburg, O = ACME Networks, CN = www.example.com, emailAddress = admin@acmenet.ru error 18 at 0 depth lookup:self signed certificate OK |
Это означает, что для этого сертификата, в папке /etc/pki/tls/certs
отсутствует необходимая информация для проверки. Необходимо убедиться, что в этой папке присутствует проверяемый сертификат, а так же присутствуем симлинк с хэшем вместо имени, на проверяемый сертификат. Если симлинка нет – его необходимо создать:
This means that the certificate in the folder /etc/pki/tls/certs
is missing information required for validation. You must make sure that this folder is present the certificate being validated, as well as present a symlink with a hash instead of the name on the certificate being validated. If where is no special symlink – you need to create:
1 2 |
$ cd /etc/pki/tls/certs $ ln -s $CRT `openssl x509 -hash -noout -in $CRT`.0 |
Where $CRT
is the file name of the certificate.
If you plan to sign the certificate in «an adult way», on the side, you need to create a private key and request to obtain a certificate:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
$ ./certroutine.sh genkey Generating RSA private key, 2048 bit long modulus ............................................+++ .....................................+++ e is 65537 (0x10001) $ ./certroutine.sh gencsr $ ./certroutine.sh verifycsr verify OK Certificate Request: Data: Version: 0 (0x0) Subject: C=RU, ST=North-West, L=Saint-Petersburg, O=ACME Networks, CN=www.example.com/emailAddress=admin@acmenet.ru Subject Public Key Info: Public Key Algorithm: rsaEncryption Public-Key: (2048 bit) Modulus: [...] Exponent: 65537 (0x10001) Attributes: Requested Extensions: X509v3 Basic Constraints: CA:FALSE X509v3 Key Usage: Digital Signature, Non Repudiation, Key Encipherment Signature Algorithm: sha256WithRSAEncryption [...] $ cat /etc/pki/tls/certs/www.example.com.csr -----BEGIN CERTIFICATE REQUEST----- [...] -----END CERTIFICATE REQUEST----- |
The contents of the csr
file, you must send in a company that will certify your certificate.
Also, you can use a script like this:
1 2 3 4 5 |
$ CN="www.example.com" ./certroutine.sh genkey $ C="RU" ST="North-West" L="Saint-Petersburg" O="Example Org" CN="www.example.com" \ EM="hostmaster@example.com" SAN="mail.example.com" ./certroutine.sh gencsr $ C="RU" ST="North-West" L="Saint-Petersburg" O="Example Org" CN="www.example.com" \ EM="hostmaster@example.com" SAN="mail.example.com" ./certroutine.sh gencrt |
If you use a free certificate from StartSSL, do the following:
1 2 3 |
$ cd /etc/pki/tls/certs $ wget https://www.startssl.com/certs/sub.class1.server.ca.pem $ ln -s sub.class1.server.ca.pem `openssl x509 -hash -noout -in sub.class1.server.ca.pem`.0 |
Otherwise verification certificate will receive an error:
1 2 3 |
$ openssl verify mail.example.com.crt mail.example.com.crt: C = RU, CN = mail.example.com, emailAddress = hostmaster@example.com error 20 at 0 depth lookup:unable to get local issuer certificate |