Client Authentication with SSL

Client Authentication with SSL

Most of you will be aware that I’m in the process of setting up a new box
for the website. As part of that process, I’m strengthening some of the administration functions.
Specifically, I’m adding client authentication to make that that only my browser can access these
features. In short, only specific people will be able to access certain areas of my website. These
people will be authenticated using client authentication.

If you’re actually looking for how to set up an https server, please try Apache with SSL.

Or if you’re looking for something more simple than certificates, you could just use passwords.

But first, let me introduce a few terms and explain a few things in order to give you a bit of background.

SSL
Secure Socket Layer
This protocol is commonly used on websites when encryption is required (not quite, but see https below). Most websites selling goods
should be using SSL. If they aren’t, the information passed between your browser and their website
is in clear text, readable by anyone who can sniff it. Now that’s unlikely that someone will, but it
is quite possible.
https
HyperText Transmission Protocol, Secure
This is the protocol used between the browser and the website. Underneath, it’s just SSL. This is why some websites
start with http://www.example.org/ and others are https://secure.example.org/. Those using https are using the secure
version of the http protocol.
OpenSSL
OpenSSL is a project which delivers the SSL protocol, tools, and libraries in a
freely available package. This is what FreeBSD uses for its SSL implementation.
Client Authentication
This is the ability of a webserver to verify who is at the other end of the browser. There is more than
one way to authenticate a client, but we will be concentrating on certificates (you could also look at
using passwords). More correctly
the website requests that a certificate be provided.
As you read this article
it will become clearer just how this process is performed.

Other resources

Introducing SSL and Certificates using SSLeay
by Frederick J. Hirsch.

We’re going to be using X.509 certificates so perhaps this document might be useful:

http://java.sun.com/products/jdk/1.2/docs/guide/security/cert3.html

Certificates

Certificates tell us who is who. A certificate ensures that the website you are talking to is indeed the website you think it is
and who it says it is. But how can you trust that a certificate hasn’t been forged. Because it’s been signed by someone you trust. Well, not
necessarily someone that you personally trust, but someone that is widely regarded as a Trusted Authority. For example,
Baltimore,
RSA,
VeriSign and,
Thawte each issue certificates. If I look at my MS IE browser, I can find a long list of trusted root certicate
authorities. Your broswer probably contains a similar list. https and SSL is all about trust. This trust has to start somewhere. Usually it starts
with a signing authority which is trusted implicitly. From there, anything signed by that authority can be trusted. And so on… My description is
a rather simplistic approach to what can be a very complex matter. But it should suffice for what we’re trying to accomplish here.

The whole idea of SSL is to get the data securely between a web
server and a client. That is accomplished by encryption. The first
time a client accesses a web server that uses SSL, the client
is presented with an the certificate. This information
allows the client to determine three important things:

  1. The certificate has not expired yet.
  2. The certificate was created for the web server now being accessed.
  3. The certificate is signed by someone the client trusts.

If any of these three conditions are not met, the client browser will display a popup
that explain the violations and requests premission to continue browsing.

When you install an SSL-capable browser, it should include
a list of certificates of widely known trusted parties. Part of the reason
why you don’t see any popup certificate window when you enter
Amazon’s secure area is that their certificate was signed by an authority
known to your broswer.

For our purposes, we’re going to fake it. We’re going to create our own certificate authority.
For our own personal use. We’ll call it a personal CA. And we’ll use it to create personal certificates.
We could ask a real certificate authority to give us a certificate signed by them. But we don’t need that.
Plus, that signing process normally costs money. In this instance, I’m the only person that’s going to be using this certificate. I trust myself.
So I don’t need someone else to create the certificate when I can do it myself. I won’t be able to use this certificate for “real” purposes. It can be
used only
for my own use. Nobody else will trust it. So it’s useful for commercial purposes (i.e. I won’t be able to put it on my webserver and expect
people to give me their credit card details). If you are going to need a real certificate, pay your money and get one.

Certificate Authority

For this step, I found HOWTO: Creating your own CA with OpenSSL by
Pheng Siong Ng to be very useful. With this information, I was able to create my own certification authority (CA) with OpenSSL (note that
VeriSign is also a CA, albeit a much better known CA than the one you just created). Then I used that CA to sign a certificate request. This is what VeriSign
would do if you ask them for a certificate. If you have more than one web server in your organisation, it is a good idea
to have the same CA sign all of the certificates.

The HOWTO document referenced above actually does more than just create a CA. It also
shows you how to create a server certificate and then sign it. I think it’s important to
distinguish between the two processes, so I will break up the HOWTO steps into two sections:

  • Creation of a CA
  • Server Certificate

Certificate Authority – creation

I’ll outline the steps I took but please refer to the primary document for full information on what I’m doing here.

  1. Create a directory where I can keep all my work in one clearly defined place:
       mkdir ~/CA

    This is where I did all my CA work.

  2. Copy CA.pl and openssl.cnf into ~/CA. First, I had to find these files. I used
    locate:

    $ locate CA.pl
    /usr/src/crypto/openssl/apps/CA.pl
    /usr/src/crypto/openssl/apps/CA.pl.in
    /usr/src/crypto/openssl/doc/apps/CA.pl.pod

    With a similar command, I found /usr/src/crypto/openssl/apps/openssl.cnf.
    If you don’t have /usr/src loaded, you can get these files directly from
    the CVS repository.
    Please take the revision which is relevant to the version of FreeBSD you have installed. For example
    these are the files you want for FreeBSD 4.3 as of the time of writing:

  3. Apply the patch supplied by Ng Pheng Siong. This extends the date range of the certificate. The default value for my
    script was 365 days. The patch changes it to three years. I actually opened CA.pl and searched for $DAYS and manually replaced all instances
    with -days 1095.
  4. Create the new CA:
       perl CA.pl -newca

    Now ~/CA/demoCA/cacert.pem contains
    the certificate for your new [personal] certificate authority.

Server Certificate – creation

In this section we’ll create a server certificate request and then sign that request
using the CA we created in the previous section.

  1. Generate a certificate request.
       perl CA.pl -newreq
  2. Sign that request. This is what a Trusted Authority does for you.
       perl CA.pl -sign

    Had you wanted a third party to sign your certificate for you, you would
    send the certificate request to them, they would sign it, and send it back to you.
    You would use that certificate. Since we are not going to do this, we will sign our own certificate. That
    is why our certificate will be known as Self Signed SSL Certificate.

  3. I then extracted the private key into a separate file:
       openssl rsa < newreq.pem > newkey.pem

File names should reflect file contents

For ease of use, I moved things around so the file names reflected the file contents.

mv newcert.pem server_cert.pem
mv newkey.pem  server_key.pem
mv newreq.pem  server_req.pem

OK. What did I just do?

In summary, you now have the following items:

  • ~/CA/demoCA/cacert.pem – the CA’s certificate. You’ll need to move this to your web server.
    See later in this article. This is destined for SSLCertificateFile.
  • server_cert.pem – the server certificate you signed. This will be used in a later step to create a
    client side certificate which you can load into your browser. This will become SSLCACertificateFile.
  • server_key.pem – the plain text (encrypted) private key for the server certificate.
    Private keys are the secret part of the certificate. Therefore we don’t want them to be world readable.
  • server_req.pem – the encrypted private key for the server certificate and the original certificate request.

Create the secure area of your website

The creation of an https server is beyond the scope of this article. Perhaps
Apache with SSL will help you with that. What I’m going to
show you is how to allow clients to visit most of the website but require authentication
to visit a particular URL. I found exactly what I wanted at the
How To section of the mod_ssl
website. I’m using the mod_ssl port on my web server.

In this example, we want to control access to the /stuff section of our website.
For example, people browsing to http://www.example.org/stuff/ will require
a certificate. If you want to secure a different area of your website, make adjustments to
the below as appropriate.

I actually used a greatly reduced version of the information found in the “second method” listed
at the above URL. I added this to the VirtualHost defined for my server:

SSLEngine       on
SSLProtocol     all
SSLCipherSuite  HIGH:MEDIUM

SSLCertificateFile      /usr/local/etc/apache/ssl.crt/server_cert.pem
SSLCertificateKeyFile   /usr/local/etc/apache/ssl.key/server_key.pem

SSLVerifyClient none

SSLCACertificatePath    configuration/certificates
SSLCACertificateFile    configuration/certificates/cacert.pem

<Location /stuff>
     SSLVerifyClient require
     SSLVerifyDepth  1
</Location>

I’ll explain some of the above with the following:

configuration/certificates/cacert.pem
created when we made our own CA.
It is the certificate for the CA. This was the first part in the CA HOWTO.
server_cert.pem
the server cerficate which we created during the second part of the CA HOWTO
server_key.pem
The key for the cerficicate. Keep this safe and secure.
Location
This is similar but still quite different from a
Directory directive and I’ve come to like it better. It allows you to specify
the URL instead of the file system.
Location is URL
specific, and not [necessarily] related to the file system at all. It is with the location
directive that I specify the secure area of the website.
SSLVerifyClient
This directive mandates that the client has to present a valid Certificate.

SSLVerifyDepth
directive indicates that the client client certificate can be self-signed or has to be signed by
a CA which is directly known to the server (i.e. the CA’s certificate is under
SSLCACertificatePath). In this case, if the secure area of the webserver is https://example.org/stuff/.

After setting up the above directives, you should verify the settings:

/usr/local/sbin/apachectl configtest

and make any changes as necessary. Then I would stop and start the server. This is
necessary because you are changing certificate information.

/usr/local/etc/rc.d/apache.sh stop
/usr/local/etc/rc.d/apache.sh start

You should then check for any error messages:

$ tail /var/log/httpd-error.log
[notice] caught SIGTERM, shutting down
[notice] Apache/1.3.20 (Unix) PHP/4.0.6 mod_ssl/2.8.4 OpenSSL/0.9.6 
         configured -- resuming normal operations

Converting the certificate to pkcs12 format

The signed server certificate to be converted into the format used by programs
such as Netscape, MSIE and MS Outlook. Fortunately, I’ve been pointed at
the right place by my
friend Eric Rosenquist. To do the conversion I used this command:

$ openssl pkcs12 -export -in server_cert.pem -inkey server_key.pem -out iestuff.p12
Enter Export Password:
Verifying password - Enter Export Password:

Make up a password, use it, and remember it.
This password will be required when you go to import the certificate into your browser. Remember it.

Security considerations

Be careful with your certificates and keys. If someone steals your certificate, they can’t be
authenticated over SSL as you unless they also have your private RSA key.
Your private key is included in the .p12 file. Thus, if someone gains
access to your .p12 file, they can impersonate you. Simply being aware of this is a good start.

Import the certificate

If you were to browse to your secure area now, you would be warned about the site certificate.
Since we know we created our own certificate, we could view the certificate to verify that it’s the one we expect,
and then click on Yes to proceed. Then you will be presented with a message asking
which certificate you wish to use. You would also be given a list of certificates to select
from. This step allows you to import a certificate into your browser. Instructions are supplied
only for MSIE.

You’ll need the iestuff.p12 created in the previous section. Then perform these steps:

  1. select Tools | Internet Options | Content | Certificates | Import….
    Or you could just double click
    on the .p12 file…
  2. From the Certificate Wizard Import Wizard, click on Next
  3. Use the Browse button to select the iestuff.p12 file.
  4. click on Next
  5. Enter the password you used to create the pkcs12 file
  6. click on Next
  7. I selected the default option to automatically store the certificate and clicked on Next
  8. click on Finish

Revoking a certificate

A CA can revoke a certificate it has issued. This may be for a number of reasons but a prime
reason would be a certificate compromise: someone has accessed the private key associated with a certificate
and it needs to be revoked for security reasons. Each CA should publish a list of revoked certificates. This
list is known as a Certificate Revocation List (CRL). Normally these lists are publically availble so that
a server can check it before accepting a given certificate.

That said, in my instance, I’m not doing a CRL yet, because I’m the
only person using these certificates.

These resources might help:

Browsing again

I found that I had to stop and restart my broswer in order for the certificate to “take”. I think it caches old
results from the previous attempts. After a restart, I broswed again to the secure area of my website. I was
presented, again, with the security alert message. But if you created
a certificate which matches the name of your website, you should see this picture
instead. After accepting that
server certificate, I was presented with the list from before,
only this time, it contained my imported certificate. I selected that certificate.
Had I had more than one certificates installed on my browser, I would have choosen the right one for the site I’m browsing.
After the certificate was selected, the server authenticated me, and I was allowed into the secure area of my website.

Thanks

I thank the following people, who appear in no particular order, for their help in composing this article.

Ryan Wamsley
Pointing out some errors and suggesting some additions.
Sean O’Riordain
Reviewing, providing some hints, and some terminology lessons.
Yonatan Bokovza
Suggestions for clarification, initial review.
Sylvain Maret
For reminding me about CRL

It’s very useful to have technical reviewers. My understanding was greatly enhanced
by their feedback. It is appreciated.

Summary

SSL is a protocol for ensuring that your communications are encrypted and secure. OpenSSL is an implementation of SSL.
Certificates are used to ensure people and/or websites are who they say they are. You can use SSL client certificates to
restrict access to
various areas of your websites. Or indeed the whole website (I didn’t cover that part, but that is easily extended; read the
modSSL how to).

The above should get you started. If you had to do something different, please
add your comments.

24 thoughts on “Client Authentication with SSL”

  1. select Communicator | Tools | Security Info | Certificates | Yours
    select Import a Certificate
    Double click the file iestuff.p12
    enter the password you used to create the pkcs12 file
    and so forth …

    1. You’re welcome. I spent a great deal of time trying to find out how to get SSL going on this box (the colocated box on which this web server resides). Glad to know it works for others too.

  2. IE 6 seems to not want to work.
    I can import the .p12 file and go to the https://domain site, it prompts for the key selection, then i get a 404.

    Netscape 6.1 i cant even figure out how to import, maybe I’m missing something…

    Any thoughts / help?

  3. Open sll with free bsd make a perfect combo in developing secure online applications. The article on Client authentication with SSL is very informative. The portion of the article that provides of creating personal certificates is very informative and interesting.

  4. Christopher Masto

    You seem to be exporting your SERVER certificate and importing it into your web browser. That’s rather strange and confusing. You should probably be creating a separate client certificate (indeed, a separate one for each client).

    An important detail that seems to be missing in this article is what to enter when creating the certificate requests (CA.pl -newreq). For a server, it’s critical that the "Common Name" be the name of your site (www.freebsddiary.org, for example). Client certificates should use the name of the person the certificate will be identifying.

    1. Patrick Sandberg

      I totally agree with your comment to the Client Certificate report on The FreeBSD Diary, he does provide the server certificate to the client, that is ok if you only want to prove "This is really server xxx.com, says this yyy CA, trust me", but if you want to check out the client from a server perspective, how do you do it?
      When I enable verify client certificates I never get IE 5.5SP2 to provide any certificate, my guess is that I have not create the client certificate in such a way to associate it with my specific website (so that IE knows what certificate to show at what server) ? But I’m not sure, any good pointers on how to create client certificates (step by step) and how to get them to work with your server?

      Thanks,
      Patrick

    2. I agree, this is not enough for client authorization. I will try today the following:

      1. Start this howto and create a CA, a Server Certificate and configure Apache, but NOT convert the certificate to pkcs12 format.

      2. Then I will create another "Server Certificate", which I will call Client Certificate, and use the client name in the CN field.

      3. I will convert the second ceritificate, Client Certificate to pkcs12 format, put it on a floppy and give it to a client

      4. The client will install the pkcs12 file in his browser

      If this does not work, I will post a message here, so if there’s no other messages here from me, the above procedure worked…

  5. Using PKCS#12 for getting server cert into browser is overkill.

    But sending your server’s PRIVATE KEY to the client PC is an absolute NO-NO!

    What yous should do:
    you should import your CA’s certificate (or, if you really wish, your server’s cert) into browser in their native .PEM format. DER would also work, but you have them in PEM already.

    How to do it:
    – copy the cacert.pem to any place in the server where it can be accessed by browser.
    – in your web server config, the MIME type for .pem files must be application/x-x509-ca-cert. If it is not, set it to be. Or define a custom extension, like .cacert, with the same MIME-type.
    – point your browser to this file, open it, view it, click ‘install’, answer ‘yes’ to most questions.
    voila!

    Your current suggestion – export the server’s private key to the outside world – kills the whole idea of using SSL, you could as well just use plain HTTP.

    1. Kaur wrote:
      >
      > Using PKCS#12 for getting server cert into browser is
      > overkill.

      Why?

      > But sending your server’s PRIVATE KEY to the client PC is an
      > absolute NO-NO!

      Could you please copy and paste exactly what is being done incorrectly? With that I can amend the document. Without it, I have no idea what, exactly, is wrong. Also helpful would be the corrections in addition to the original.

      > Your current suggestion – export the server’s private key to
      > the outside world – kills the whole idea of using SSL, you
      > could as well just use plain HTTP.

      I agree. Now, where is it, exactly, that the server’s private key is being given to the outside world? It’s a big document, and it’s not like it was written yesterday.

    2. >> But sending your server’s PRIVATE KEY to the client PC is an
      >> absolute NO-NO!
      >
      >Could you please copy and paste exactly what is being done
      >incorrectly? With that I can amend the document. Without it,
      >I have no idea what, exactly, is wrong. Also helpful would be
      >the corrections in addition to the original.

      All of section "Converting the certificate to pkcs12 format" is wrong. PKCS#12 is used for transporting a private key of a client certificate to the browser. There should be no need to convert the server certificate to PKCS#12 format. Basically you are handing out your server secret key to everyone to use as a client certificate when you give them the iestuff.p12 file.

      So, to do it correctly, convert your client certificate (if you need one) to PKCS#12 to get the private key into the browser. Never the server one.

      To make the client to trust the server certificate import the CA certificate in the client. It’s the demoCA/cacert.pem file. I am on a Linux box right now, but basically in Windows you should be able to just double click on the file and it will ask you whether you want to import and trust it. Possibly you must rename the file to .crt, .cer or .der. Don’t remember right now.

      However you cannot expect (or at least in an ideal world you would not be able to expect) your customers to trust your own homemade CA certificate. Instead you would buy your server certificate from a real CA, and then you would not need to do anything on the client side.

      Hope this helps.

      /Erik

      1. Erik wrote:

        > All of section "Converting the certificate to pkcs12 format"
        > is wrong. PKCS#12 is used for transporting a private key of a
        > client certificate to the browser. There should be no need to
        > convert the server certificate to PKCS#12 format. Basically
        > you are handing out your server secret key to everyone to use
        > as a client certificate when you give them the iestuff.p12
        > file.

        Ahh, the goal was to convert the client certificate. Not the server certificate. I bet it’s an error propogated from copy/paste.

        > So, to do it correctly, convert your client certificate (if
        > you need one) to PKCS#12 to get the private key into the
        > browser. Never the server one.

        Agreed.

        > However you cannot expect (or at least in an ideal world you
        > would not be able to expect) your customers to trust your own
        > homemade CA certificate.

        Well, yes. I was creating a client certificate for my own use. I don’t want just anyone browsing the admin pages of this web site….

        > Instead you would buy your server
        > certificate from a real CA, and then you would not need to do
        > anything on the client side.

        Sound advice for commercial site. Not practical for me though.

        Thank you.

    3. Andrew,

      this isn’t pedantry – making the mistake of exporting your server’s private key invalidates the entire process. Would you say it was pedantic for banks to advise people not to write their PIN number on their bank cards in dayglo ink? Practical, yes, pedantic, no.

      Otherwise, yes, a good article. For reference, here are the MIME type lines needed for apache’s conf file to allow you to place server certs, crls and client certs – encrypted, of course – onto your site.

      AddType application/x-x509-ca-cert crt
      AddType application/x-pkcs7-crl crl
      AddType application/x-x509-user-cert p12

      For an admittedly technical lowdown on the various PKCS formats, see:

      http://www.rsasecurity.com/rsalabs/pkcs/index.html

      Also good intro stuff on certificates, see the stunnel site:

      http://www.stunnel.org/faq/certs.html#ToC1

  6. Hi
    A little confused. What is the steps to follow after verisign send you the cert? Do I copy it to demoCA/cacert.pem and the run perl CA.pl -sign?

    Thanks

  7. I’ve tried this VERY GOOD tutorial, but with the change about making a client certificate, for importing to the client.
    It does not work in IE (i’ve tried in version 6 and 5.5), but it work perfectly in Opera.
    Does anybody knows what i have to change in the Apache VirtualHost configuration or in the IE settings?

    I need help!!!

  8. Does anybody know about source code examples or other information about creating client certificates online? (using a one time password for example).
    Eg html code for Netscape and IE for generating keypair and how to handle them on the server. Especially when usin Apache and sll in combination with a servlet engine?
    Thankfull for any help.

  9. Martin Johnson

    Hi,

    I have successfully imported a myown CA public key and Client cert signed by this CA into IE 5.5

    I have attempted to access my Tomcat server that requires clients to authenticate. Hence the appearance of the dialog requesting "Select the certificate to use etc…". Yet the dialog list is empty there is not cert to select.

    Your site states

    >But if you created a certificate which matches the name of your website, >you should see this picture instead

    Perhaps this is what I’m missing though I dont quite understand how do I set this up?

    Regards.

Leave a Comment

Scroll to Top