[Home] You are not logged in. Login here

Just my stuff

Apache mod_ssl mutual authentication

Certificates are usually used to authenticate the server only: you connect to your banks site, and you know that it’s the bank you connected to, because the certificate they send to your browser is valid and signed by a Certification Authority you (or your browser) trust. But you can use Certificates to authenticate the user too, and that is called mutual authentication. How does it work?

First of all we need to generate a CA certificate, that we then are going to use to sign the server and the client cert:

#generate the key
openssl genrsa -out ./CA/freshCA.key 1024
#generate a certificate request
openssl req -new -key ./CA/freshCA.key -out ./CA/freshCA.csr
#self-sign the request
openssl x509 -req -days 3650 -in ./CA/freshCA.csr \
-out ./CA/freshCA.crt -signkey ./CA/freshCA.key

now we have a valid, self-signed CA certificate.
Next we are going to generate a certificate for the web server, but first we need to change some defaults in
/etc/ssl/openssl.cnf
and create some initial files:
vi /etc/ssl/openssl.cnf #and change demoCA to CA
mkdir -p CA/newcerts
touch CA/index.txt
echo '100001' >CA/serial #this is the first serial number of the certificate you are going to generate

Next, generate the server certificate:
openssl genrsa -out ./server/keys/fresh.key 1024
openssl req -new -key ./server/keys/fresh.key -out ./server/requests/new_server.csr
openssl ca -days 3650 -in server/requests/new_server.csr -cert \
./CA/freshCA.crt -keyfile ./CA/freshCA.key \
-out ./server/certificates/new_server.crt

We can use this certificate in our apache config file right away:
ServerName new_server:443
SSLEngine on
SSLCertificateFile conf/certs/server/certificates/new_server.crt
SSLCertificateKeyFile conf/certs/server/keys/new_server.key
SSLCACertificateFile conf/certs/CA/freshCA.crt

Now we have apache listening on 443 for requests, using the new_server.crt certificate that is signed by freshCA.crt.
Now we can generate a client certificate for a user:
#first generate a key
openssl genrsa –des3 –out ./user/keys/simon.key 1024
#then the request
openssl req –new –key ./user/keys/simon.key –out ./user/requests/simon.csr
#then sign it
openssl ca -in ./user/requests/simon.csr \
–cert ./CA/freshCA.crt –keyfile ./CA/freshCA.key \
–out ./user/certificates/simon.crt
#convert it to p12
openssl pkcs12 -export -in ./user/certificates/simon.crt -inkey ./user/keys/simon.key -out simon.p12

This generates a new, signed certificate that can be installed in the browser. Just put it somewhere on your server for the user to download.
Once the client certificate is installed on the browser side, we have to instruct apache to check it. Just add
SSLVerifyClient require
SSLVerifyDepth 2

to your config file, and nobody without a valid client certificate will be able to connect on 443 of your server. You may want to forward the email field, or the Common Name of the client certificate to your web application to be able to know who the user is:
#Forward Client certificate CN
RequestHeader set X_SSL_CLIENT_DN_Email "%{SSL_CLIENT_S_DN_Email}s" 
RequestHeader set X_SSL_CLIENT_DN_CN "%{SSL_CLIENT_S_DN_CN}s" 

This makes those fields available in the request headers for your app to consume.

If you ever need to revoke a cert, the steps are:

openssl ca –revoke ./user/certificates/simon.crt
#generate the certifacate revocation list
openssl ca –gencrl –out ./CA/freshCA.crl

and tell apache to check the revocation list with this line in your config file:
SSLCARevocationFile conf/certs/CA/freshCA.crl

Other random stuff:
- Strip the passphrase from a key file:

openssl rsa -in key.pem -out newkey.pem

- Convert a pfx file to a key and a crt file:
openssl pkcs12 -in filename.p12 -nocerts -out privatekey.key
openssl pkcs12 -in filename.p12 -clcerts -nokeys -out sslcert.crt

- Convert a pem file to a pkcs12 file:
openssl pkcs12 -export -in cert.pem -inkey key.pem -out cred.p12

- Generate a self-signed certificate
openssl req -new -newkey rsa:1024 -days 365 -nodes -x509 -keyout www.example.com.pem  -out www.example.com.pem

Avatar curt1s said...

How do we add the client certificate to the client’s web broswer? I keep getting errors when I try to do this.

Thanks

Mon Aug 10 15:41:59 +0200 2009
 
Comments for this post have been disabled