SSL (HTTPS) on your Development WebServer

It took me a while and finally found a working, but a bit ugly, solution. Not to bore you with the details, here are the step by step instruction on how to get HTTPS working on your development web server. Please note, this is not a good setup for live web servers, you will have to take security into account if you use this on a publicly available web server.

The first steps are taken from a web-archive from the Apple website (the page is no longer available) and I have altered the commands and paths so they fit nicely in a 10.6 or higher installation. The comments are 90% original Apple instructions.

Please note; This post is the second post in a series to build the “perfect” setup. See ‘The “Ultimate” Guide …’ or the menu on the right side for a complete list of related posts.

The first thing you need to do is generate the keys and certifications for the server. This requires using the Terminal. For sanity’s sake, create a directory (Folder) on the desktop called KeyGen and change into that directory.

Shell commandmkdir ~/Desktop/KeyGen && cd ~/Desktop/KeyGen

You can now create an RSA private key and a CSR (Certificate Signing Request) for your server. An important part of private key cryptography is making sure that the parties involved in a transaction are who they say they are. This is accomplished through a third party — a trusted Certificate Authority (CA). The CA issues certificates that identify the parties, and confirms that the keys are correct and are cryptographically “signed.” Generating the CSR is the cryptographical equivalent to filling out a passport application. The CA will return the certificate (like a passport) which is used for identification and authentication.

You’re going to be self-signing the keys, so you’ll also be creating a CA key for the signature. The keys and certificates you create are purely for testing purposes. If you need to set up a production server, you should send your CSR to a proper CA, such as Verisign, for signing.

To create the RSA private key, issue the following command:

Shell commandopenssl genrsa -des3 -out server.key 2048

You will be asked for a passphrase (essentially a password for the key file) in the creation of this key. Do not forget this passphrase! You’ll have to do this all over if you forget the passphrase. You will need this passphrase later on in the process.

Now you’re ready to create a CSR (Certificate Signing Request), which is what you would normally send to a CA for signing. You’re going to sign it yourself.

You’ll be asked for some information when you start this. Most of it is pretty self explanatory, but one item, in particular, is not. Here’s what you’ll be asked for:

Shell outputCountry Name (2 letter code) [AU]: (enter your country code here)
State or Province Name (full name) [Some-State]: (Enter your state here)
Locality Name (eg, city) []: (enter your city here)
Organization Name (eg, company) [Internet Widgits Pty Ltd]: (enter something here)
Organizational Unit Name (eg, section) []: (enter something here)
Common Name (eg, YOUR name) []: (this is the important one)
Email Address []: (your e-mail address)

The entry for “Common Name” is the one that seems like it should be one thing, but is, in fact, another. For this entry, you want to enter your “Server Name” as it appears in your httpd.conf. As this is just a development environment, you can enter 127.0.0.1, which is the default IP for “localhost”. Now, keep in mind that using 127.0.0.1 is not the same as using “localhost”. The strings either match, or they don’t — Unix is like that.

Shell commandopenssl req -new -key server.key -out server.csr

You should now have two files; server.csr and server.key. Check this with

ls -la

To sign the files, you will need a key for your CA (Certificate Authority). It’s just like your server.key – a Triple-DES encrypted, 2048 bit RSA key.

Shell commandopenssl genrsa -des3 -out ca.key 2048

Again, you’ll be asked for a passphrase, which, again, you should not forget.

Now you will create a self-signed CA Certificate using the RSA key you just made.

Shell commandopenssl req -new -x509 -days 3650 -key ca.key -out ca.crt

You’ll be asked for the passphrase for the key you just made, and, again, you’ll be asked to enter information about yourself. The main difference is that here, when you are asked for your “Common Name”, you want to enter your name — not the server name or IP address. This certificate is not associated with your server — it’s associated with you. It should look something like this:

Shell outputCountry Name (2 letter code) [AU]:US
State or Province Name (full name) [Some-State]:Texas
Locality Name (eg, city) []:San Antonio
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Bogus CA
Organizational Unit Name (eg, section) []:Bogus CA for Dev
Common Name (eg, YOUR name) []:Bob Davis
Email Address []:bobdavis@mac.com

Now you have 4 files in your directory — a CA key and certificate, and a server key and certificate signing request.

The next step is the important one. This is where you sign the server.key with your ca.crt. This will provide the security assurance that browsers need to establish a secure connection. It provides the identification and verification part of the public key encryption system where the keys themselves provide the mechanism for the encryption and decryption.

The easiest way to do this is to use the sign.sh script I have taken from the mod_ssl source.

script: sign.sh (download file)#!/bin/sh
##
##  sign.sh -- Sign a SSL Certificate Request (CSR)
##  written in 1998 by Ralf S. Engelschall
##

#   argument line handling
CSR=$1
if [ $# -ne 1 ]; then
    echo "Usage: sign.sign <whatever>.csr"; exit 1
fi
if [ ! -f $CSR ]; then
    echo "CSR not found: $CSR"; exit 1
fi
case $CSR in
   *.csr ) CERT="`echo $CSR | sed -e 's/\.csr/.crt/'`" ;;
       * ) CERT="$CSR.crt" ;;
esac

#   make sure environment exists
if [ ! -d ca.db.certs ]; then
    mkdir ca.db.certs
fi
if [ ! -f ca.db.serial ]; then
    echo '01' >ca.db.serial
fi
if [ ! -f ca.db.index ]; then
    cp /dev/null ca.db.index
fi

#   create an own SSLeay config
cat >ca.config <<EOT
[ ca ]
default_ca              = CA_own
[ CA_own ]
dir                     = .
certs                   = \$dir
new_certs_dir           = \$dir/ca.db.certs
database                = \$dir/ca.db.index
serial                  = \$dir/ca.db.serial
RANDFILE                = \$dir/ca.db.rand
certificate             = \$dir/ca.crt
private_key             = \$dir/ca.key
default_days            = 3650
default_crl_days        = 30
default_md              = md5
preserve                = no
policy                  = policy_anything
[ policy_anything ]
countryName             = optional
stateOrProvinceName     = optional
localityName            = optional
organizationName        = optional
organizationalUnitName  = optional
commonName              = supplied
emailAddress            = optional
EOT

#  sign the certificate
echo "CA signing: $CSR -> $CERT:"
openssl ca -config ca.config -out $CERT -infiles $CSR
echo "CA verifying: $CERT <-> CA cert"
openssl verify -CAfile ca.crt $CERT

#  cleanup after SSLeay
rm -f ca.config
rm -f ca.db.serial.old
rm -f ca.db.index.old

#  die gracefully
exit 0

Save the script in ~/Desktop/KeyGen and execute;

Shell commandsh sign.sh server.csr

You should get something like this, but with the information you entered for the server.csr:

Shell outputCA signing: server.csr -> server.crt:
Using configuration from ca.config
Enter PEM pass phrase:
Check that the request matches the signature
Signature ok
The Subjects Distinguished Name is as follows
countryName :PRINTABLE:'US'
stateOrProvinceName :PRINTABLE:'Texas'
localityName :PRINTABLE:'San Antonio'
organizationName :PRINTABLE:'Testing'
organizationalUnitName:PRINTABLE:'Testing'
commonName :PRINTABLE:'127.0.0.1'
emailAddress :IA5STRING:'bobdavis@mac.com'
Certificate is to be certified until Sep 14 23:09:20 2002 GMT (365 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 verifying: server.crt <-> CA cert
server.crt: OK

Next step is to “install” the keys;

Make a directory in your /etc/apache2 called ssl.key

Shell commandsudo mkdir /etc/apache2/ssl.key

Copy all of the contents of your working directory to the ssl.key directory you just made.

Shell commandsudo cp -r * /etc/apache2/ssl.key/

One more step — and it’s another step that would not have a place in a production environment, but definitely makes life with your development system better: you’re going to remove the passphrase requirement from the server key by removing its encryption.

As things stand, when you start Apache, you will be prompted for a passphrase to read the private key. While this is fine for those who start and stop Apache manually from the command line every time, it does create some problems for those of us who have Apache (a.k.a. Web Sharing) start up automatically every time the system reboots. The system will hang on startup, patiently waiting for a passphrase that will never come — because there’s no way to enter the passphrase you’ve given the key! You’ll have to either boot into Mac OS 9 or boot into verbose mode to clear this problem if you forget.

Removing the pass phrase requirement is dangerous in a production environment, but acceptable for testing (especially if you enter information in your certificate request that makes it clear that this is a testing certificate, and not for production use).

Enter the following:

Shell commandcd /etc/apache2/ssl.key
sudo cp server.key server.key.original
sudo openssl rsa -in server.key.original -out server.key

You’ll be asked for your sudo password and then for your key-passphrase. Comparing the two files server.key and server.key.original will show that they are now very different and that server.key.original contains a line stating, “Proc-Type: 4,ENCRYPTED”, that the decrypted file lacks.

The following steps are taken from the blog of Larry Ullman and adapted to service our needs.

In the /etc/apache2/httpd.conf file, find the line that says

LoadModule ssl_module libexec/apache2/mod_ssl.so

and make sure it does not have a # at the front of it. If it does, that means the line is commented-out, making that module inactive.

Go a little bit further down and remove the # from in front of:

Include /private/etc/apache2/extra/httpd-ssl.conf

That line includes the SSL configuration file. You can now save httpd.conf (you’ll likely need to enter the admin password at the prompt).

Next, edit the file httpd-ssl.conf, found in the /etc/apache2/extra folder. (By the way, /etc/apache2 and /private/etc/apache2 are two references to the same thing.) In the httpd-ssl.conf file, you need to edit two lines, indicating the location of the certficate and key. These two lines are a few lines apart.

The first is

SSLCertificateFile "/private/etc/apache2/server.crt"

and should be changed to

SSLCertificateFile /private/etc/apache2/ssl.key/server.crt

Then find this line

SSLCertificateKeyFile "/private/etc/apache2/server.key"

and change it to

SSLCertificateKeyFile "/private/etc/apache2/ssl.key/server.key"

That’s it there. Now save httpd-ssl.conf and close it (again, you’ll likely need to enter the admin’s password).

Now you can test how it worked. To do so, go to the Terminal and type:

Shell commandsudo apachectl configtest

If it says Syntax OK, you’re good to go. If it gives an error, make a note of what it is and search the Web or post a question here.

If you got the Syntax OK message, you just need to restart Apache. In System Preferences > Sharing and uncheck and recheck Web Sharing.

 

Author: Remon Pel

WebDeveloper though not WebDesigner

Leave a Reply

Your email address will not be published. Required fields are marked *