Jeffrey Belt

Another Computer Geek

Becoming your own X.509 Certificate Authority

This information copied from David Pashley's site.

Normally when you configure a server to use TLS or SSL you have two choices; Either you pay someone like Verisign or Thawte to sign a certificate or you generate a self-signed certificate. However there is an alternative, which is to generate your own certificate authority or CA. This article will explain how to generate your CA and sign and revoke certificates, as well as how to get common applications to trust your CA.

Why Become Your Own Certificate Authority

Which route you choose depends on your circumstances and why you need a certificate. For a large public service like an e-commerce website, you’ll want a certificate signed by an established trusted root CA, who, like Verisign, have their root keys bundled with web browsers and operating systems. This allows anyone to trust your server is the server it claims to be and traffic is encrypted, without having to install any additional certificate. The downside to this is the cost of getting a certificate. At the time of writing, Verisign were charging 2,480USD for a 3 year 128bit certificate. Other companies can provide you with certificates for around 100USD for a year.

If on the other hand you have a personal website with a webmail application on, you probably want to use https to prevent anyone sniffing your login password. For a personal site it isn’t worth paying 100USD a year for a trusted certificate. In this case you’d generate a self-signed certificate. That is a certificate signed by itself. This allows you to use https for encryption, but your browser can not trust the server as there is no chain from a trusted root to the server certificate. The client will probably also give you several warnings that it isn’t trusted and give you the option of whether you want to trust it. The advantage of self-signed certificates is that they are free, but the disadvantages are that you can’t use them for trust and your client will complain every time you connect.

If you have a small (or large) organization, you may have several different services that need encrypting. You’ll need one for every website (e.g. www, intranet, wiki, webmail) and you’d need one for mail services. This soon mounts up to quite a few certificates. Because you have a limited number of users, it becomes possible to generate your own root CA and distribute the public key to your users. This has the advantages of being free and can be used for trusting servers, but at the expense of requiring your users to import your root certificate. This article will explain how to go about generating your certificate authority and using it to sign and revoke certificates. It will also explain how to import the root certificate into common applications.

Creating A Root Certificate Authority

We will be using the openssl program which is included in the OpenSSL SSL suite. It should be possible to use other tools like GnuTLS or SSLeay, but they are not described here.

The first thing to do is to create a location for storing your files. You need to keep your private key secure from unauthorized access. Create a new directory for your CA directory layout. All the commands will be run from inside this new directory.

root$ mkdir -p root-ca/{conf,private,public}

root$ chmod 400 root-ca/private

root$ cd root-ca

I like to use a separate configuration file for the CA, rather than use the central configuration file. The central file is fine for generating certificates and signing requests, but the CA needs some special options. During each section I’ll build up the config file until we have a complete config file for the CA. Create conf/openssl.cnf with the following contents:

[ req ]

default_bits            = 2048

default_keyfile         = ./private/root.pem

default_md              = sha256

prompt                  = no

distinguished_name      = root_ca_distinguished_name

x509_extensions = v3_ca

[ root_ca_distinguished_name ]

countryName             = UK

stateOrProvinceName     = Sussex

localityName            = Brighton

0.organizationName      = Example Inc

commonName              = Example Inc Root CA

emailAddress            =

[ v3_ca ]



basicConstraints = CA:true

The only section you need to change is the root_ca_distinguished_name options to define your location and organization that will appear in your trusted root. Once you’ve done that, you can generate your key.

root$ openssl req -nodes -config conf/openssl.cnf -days 1825 -x509 -newkey rsa:1024 -out public/root.pem -outform PEM

Generating a 1024 bit RSA private key



writing new private key to './private/root.pem'


You should now have a public/root.pem file and a private/root.pem which contains the public and private key respectively. You may want to configure the number of bits in the key by changing the rsa:1024 to rsa:2048 for 2048bit keys. You may also want to change the expiry of the key by changing the days option. I’ve generated a key that will last 5 years (1825 days).

Lets look at these files. They are base64 encoded, so they are plain ASCII files. We can also decode the files using openssl. The private key using the rsa subcommand and the public key using the x509 subcommand.

root$ cat private/root.pem
















root$ openssl rsa -in private/root.pem -noout -text

Private-Key: (1024 bit)











publicExponent: 65537 (0x10001)









































root$ cat public/root.pem






















root$ openssl x509 -in public/root.pem -noout -text



        Version: 3 (0x2)

        Serial Number:


        Signature Algorithm: sha1WithRSAEncryption

        Issuer: C=UK, ST=Sussex, L=Brighton, O=Example Inc, CN=Example Inc Root CA/


            Not Before: Apr  8 17:05:35 2006 GMT

            Not After : Apr  7 17:05:35 2011 GMT

        Subject: C=UK, ST=Sussex, L=Brighton, O=Example Inc, CN=Example Inc Root CA/

        Subject Public Key Info:

            Public Key Algorithm: rsaEncryption

            RSA Public Key: (1024 bit)

                Modulus (1024 bit):










                Exponent: 65537 (0x10001)

        X509v3 extensions:

            X509v3 Subject Key Identifier:


            X509v3 Authority Key Identifier:


                DirName:/C=UK/ST=Sussex/L=Brighton/O=Example Inc/CN=Example Inc Root CA/


            X509v3 Basic Constraints:


    Signature Algorithm: sha1WithRSAEncryption









Distributing Your Root CA Public Certificate

The easiest way to distribute your key is to put up a web page and link to your public certificate. You will need to serve it using the right mime type. Under apache you can do this using:

AddType application/x-x509-ca-cert .crt .cert .pem

We can now copy our public key to our web site as something like Example-Inc-Root-CA.crt, and direct users to to download it.

Some clients require different formats to import, so we can make life easier for our users by offering our public key in different formats. Some clients require the key in DER format.

root$ openssl x509 -in public/root.pem -outform DER -out public/root.der

Some software, like cfengine, require the filename of the certificate to be a hash of the certificate. You can generate this filename using:

root$ cp public/root.pem public/$(openssl x509 -noout -hash -in public/root.pem)

Manually Generating a Certificate Signing Request

Sometimes you need to generate your own CSR, use the following command.

root$ openssl req -new -newkey rsa:2048 -nodes -keyout yourdomain.key -out yourdomain.csr

Enter the requested information:

Common Name: The fully-qualified domain name, or URL, you're securing.

If you are requesting a Wildcard certificate, add an asterisk (*) to the left of the common name where you want the wildcard, for example *

Organization: The legally-registered name for your business. If you are enrolling as an individual, enter the certificate requestor's name.

Organization Unit: If applicable, enter the DBA (doing business as) name.

City or Locality: Name of the city where your organization is registered/located. Do not abbreviate.

State or Province: Name of the state or province where your organization is located. Do not abbreviate.

Country: The two-letter International Organization for Standardization (ISO) format country code for where your organization is legally registered.

If you do not want to enter a password for this SSL, you can leave the Passphrase field blank. However, please understand there might be additional risks.

Signing Certificate Signing Requests

we now need to add support for signing certificate signing requests (CSR). A someone will generate a CSR and give it to you to sign. You then need to check they should have the certificate they’ve asked for. If the information in the CSR is valid, then you sign it, generating a new public certificate for the CSR, which you return to the person making the request.

Add the following to your conf/openssl.cnf:

[ ca ]

default_ca              = CA_default

[ CA_default ]

dir                     = .

new_certs_dir           = ./signed-keys/

database                = ./conf/index

certificate             = ./public/root.pem

serial                  = ./conf/serial

private_key             = ./private/root.pem

x509_extensions         = usr_cert

name_opt                = ca_default

cert_opt                = ca_default

default_crl_days        = 30

default_days            = 365

default_md              = sha1

preserve                = no

policy                  = policy_match

[ policy_match ]

countryName             = match

stateOrProvinceName     = match

organizationName        = match

organizationalUnitName  = optional

commonName              = supplied

emailAddress            = optional

[ usr_cert ]




nsCaRevocationUrl =

The only options you might want to change are nsCaRevocationUrl, which clients can use to check if the certificate has been revoked and default_days which defines the length of the certificate before it expires.

We also need to set up a couple more files and directories before we can sign CSRs. We need a directory to store copies of our signed keys, so we can easily revoke them. We also need a file to store a serial number in and a file to keep an index of our signed keys.

root$ mkdir signed-keys

root$ echo "01" > conf/serial

root$ touch conf/index

Now we have the infrastructure available, we can start signing requests. The first thing to do is to view the request and make sure we are happy to sign it. The important bit is the CN=section as that is the bit that the client software will check.

root$ openssl req -in request.csr -noout -text

Certificate Request:


        Version: 0 (0x0)

        Subject: C=UK, ST=Sussex, L=Brighton, O=Example Inc,

        Subject Public Key Info:

            Public Key Algorithm: rsaEncryption

            RSA Public Key: (512 bit)

                Modulus (512 bit):






                Exponent: 65537 (0x10001)



    Signature Algorithm: sha1WithRSAEncryption





We need to be certain that the person requesting this certificate controls When we are happy with the details in the request, we can sign it using:

root$ openssl ca -batch -config conf/openssl.cnf -in request.csr -out example-ca-com.cert

Using configuration from conf/openssl.cnf

Check that the request matches the signature

Signature ok

Certificate Details:

        Serial Number: 1 (0x1)


            Not Before: Apr  8 18:29:33 2006 GMT

            Not After : Apr  8 18:29:33 2007 GMT


            countryName               = UK

            stateOrProvinceName       = Sussex

            organizationName          = Example Inc

            commonName                =

            emailAddress              =

        X509v3 extensions:

            X509v3 Basic Constraints:


            X509v3 Subject Key Identifier:


            X509v3 Authority Key Identifier:


                DirName:/C=UK/ST=Sussex/L=Brighton/O=Example Inc/CN=Example Inc Root CA/


            Netscape CA Revocation Url:


Certificate is to be certified until Apr  8 18:29:33 2007 GMT (365 days)

Write out database with 1 new entries

Data Base Updated

You should find that you now have a request.cert, which you can return to the requestor. You should also have a signed-keys/01.pem, which you can use if you ever need to revoke the signature. You should also find that conf/serial has been incremented, and that conf/index has been updated to include the new key’s details.

Revoking keys

The final step is the ability to revoke certificates that you have signed. You would probably want to revoke certificates if you discover that a certificate was incorrectly signed or someone has failed to keep their private key secure and needs to replace it. The process for revoking keys is to revoke the key itself and then generate and publish a new certificate revocation list (CRL).

The first thing to do is to add a couple of lines to the config file:

[ crl_ext ]


First we need to revoke the key using:

openssl ca -config conf/openssl.cnf -revoke example-ca-request.cert

Using configuration from conf/openssl.cnf

Revoking Certificate 01.

Data Base Updated

You should find that the only change has been to the conf/index file. Now we need to generate our CRL so users can tell it’s been revoked.

root$ openssl ca -config conf/openssl.cnf -gencrl -out example-ca-crl.pem

Using configuration from conf/openssl.cnf

Again we can decode this file using openssl crl:

root$ openssl crl -in example-ca-crl.pem -noout -text

Certificate Revocation List (CRL):

        Version 1 (0x0)

        Signature Algorithm: sha1WithRSAEncryption

        Issuer: /C=UK/ST=Sussex/L=Brighton/O=Example Inc/CN=Example Inc Root CA/

        Last Update: Apr  9 08:51:40 2006 GMT

        Next Update: May  9 08:51:40 2006 GMT

Revoked Certificates:

    Serial Number: 01

        Revocation Date: Apr  9 08:46:05 2006 GMT

    Signature Algorithm: sha1WithRSAEncryption









This file now needs to be uploaded to as this is the location we specified when we signed the certificates. Clients will look at the information in the certificate and attempt to check it against that url to see if it has been revoked. If you don’t publish it at the location in the certificates the client will never know it’s been revoked.

Importing the Trusted Root Certificate


There are two methods for installing a certificate in Firefox; from a url or from a file. To load from a url, just browse to the url and, providing the server serves the file with the right MIME type, you will be prompted for which uses you trust the certificate. You probably want to tick “Trust this CA to identify websites”. Finally click okay.

If you have the root certificate on disk, you can install it by going to Tools -> Options. Select the Advanced section and the Security tab.

Click on the “View Certificates” button and then the “Authorities” tab.

Click on “Import” and then browse to the certificate file.

Once you click open, you’ll be prompted for which uses you trust the certificate. You probably want to tick “Trust this CA to identify websites”. Finally click okay.

You can check that it’s installed correctly by scrolling down the list until you find your root certificate.

Internet Explorer

You can import the certificate into Internet Explorer by browsing the the certificate. You will be prompted if you want to open or save the file. Select Open.

You’ll be shown information about the certificate. Select Install Certificate.

Choose Place all certificates in the following store and select Browse.

Select Third-Party Root Certification Authorities and press OK.

Select Next

Select Finish and you’ll be told the certificate imported sucessfully. You can close all the dialogs.

You can check the certificate installed correctly by opening Internet Options and choosing the Certificate button from the Content tab.

Select the Trusted Root Certification Authories tab and scroll down to your certificate.

If you select View, you can view details about your certificate.


You can install your certificate as part of the ca-certificate infrastructure. You need to copy your .pem file to /usr/share/ca-certificates/ directory, add the filename to /etc/ca-certificates.conf file and then run update-ca-certificates command.

root# cp public/root.pem /usr/share/ca-certificates/Example-Inc.crt

root# echo Example-Inc.crt >> /etc/ca-certificates.conf

root# update-ca-certificates

Once you’ve done this, you can point programs at /etc/ssl/certs/ca-certificates.crt.


You can add the following line to your ~/.muttrc file.

set certificate_file=/etc/ssl/certs/ca-certificates.crt

Home        Services        Contact       How To’s        GitHub

Copyright - Jeffrey Belt - All Rights Reserved