Be your own Certificate Authority (CA)

26 Comments

This article describes how to become your own Certificate Authority (CA) and issue your own server certificates. Be advised that noone else, apart from you, your internal network's people or your friends, will or should trust this kind of certificates (self-signed). These are intended only for providing secure communication with your own services or for testing purposes.

I declare from the beginning that I am no authority on digital certificates.
This document is a summary of all the articles I have read about openssl. It describes in short how to become your own Certificate Authority (CA) and how to create and sign your own certificate requests. Make no mistake, these certificates are good only for personal use or for use in your intranet in order to provide a secure way to login or communicate with your services, so that passwords or other data is not transmitted in the clear. Noone else will or should trust these certificates.

Prerequisites

The package openssl should be installed in the machine you will use to manage your certificates or create the certificate requests.

First things first…

The openssl package comes with some scripts that can help you create your server certificates fast, but here I will describe how to set things up from scratch in a new directory, so that you can customize things later if you like or delete everything without touching openssl’s or the system’s default files. This article is based on a Fedora installation, but will do for all distributions.

Creating the necessary directories

First of all we will create a directory tree where all certificate stuff will be kept. Fedora’s default directory is /etc/pki/tls/. So, as root, we create our own directories:

# mkdir -m 0755 /etc/pki_jungle

And then we create our CA’s directory tree:

# mkdir -m 0755 \
     /etc/pki_jungle/myCA \
     /etc/pki_jungle/myCA/private \
     /etc/pki_jungle/myCA/certs \
     /etc/pki_jungle/myCA/newcerts \
     /etc/pki_jungle/myCA/crl
  • myCA is our Certificate Authority’s directory.
  • myCA/certs directory is where our server certificates will be placed.
  • myCA/newcerts directory is where openssl puts the created certificates in PEM (unencrypted) format and in the form cert_serial_number.pem (eg 07.pem). Openssl needs this directory, so we create it.
  • myCA/crl is where our certificate revokation list is placed.
  • myCA/private is the directory where our private keys are placed. Be sure that you set restrictive permissions to all your private keys so that they can be read only by root, or the user with whose priviledges a server runs. If anyone steals your private keys, then things get really bad.

Initial openssl configuration

We are going to copy the default openssl configuration file (openssl.cnf) to our CA’s directory. In Fedora, this file exists in /etc/pki/tls. So, we copy it to our CA’s dir and name it openssl.my.cnf. As root:

# cp /etc/pki/tls/openssl.cnf /etc/pki_jungle/myCA/openssl.my.cnf

This file does not need to be world readable, so we change its attributes:

# chmod 0600 /etc/pki_jungle/myCA/openssl.my.cnf

We also need to create two other files. This file serves as a database for openssl:

# touch /etc/pki_jungle/myCA/index.txt

The following file contains the next certificate’s serial number. Since we have not created any certificates yet, we set it to "01":

# echo '01' > /etc/pki_jungle/myCA/serial

Things to remember

Here is a small legend with file extensions we will use for the created files and their meaning. All files that will be created will have one of these extensions:

  • KEY – Private key (Restrictive permissions should be set on this)
  • CSR – Certificate Request (This will be signed by our CA in order to create the server certificates. Afterwards it is not needed and can be deleted)
  • CRT – Certificate (This can be publicly distributed)
  • PEM – We will use this extension for files that contain both the Key and the server Certificate (Some servers need this). Permissions should be restrictive on these files.
  • CRL – Certificate Revokation List (This can be publicly distributed)

Create the CA Certificate and Key

Now, that all initial configuration is done, we may create a self-signed certificate, that will be used as our CA’s certificate. In other words, we will use this to sign other certificate requests.

Change to our CA’s directory. This is where we should issue all the openssl commands because here is our openssl’s configuration file (openssl.my.cnf). As root:

# cd /etc/pki_jungle/myCA/

And then create your CA’s Certificate and Private Key. As root:

# openssl req -config openssl.my.cnf -new -x509 -extensions v3_ca -keyout private/myca.key -out certs/myca.crt -days 1825

This creates a self-signed certificate with the default CA extensions which is valid for 5 years. You will be prompted for a passphrase for your CA’s private key. Be sure that you set a strong passphrase. Then you will need to provide some info about your CA. Fill in whatever you like. Here is an example:

Country Name (2 letter code) [GB]:GR
State or Province Name (full name) [Berkshire]:Greece
Locality Name (eg, city) [Newbury]:Thessaloniki
Organization Name (eg, company) [My Company Ltd]:My Network
Organizational Unit Name (eg, section) []:My Certificate Authority
Common Name (eg, your name or your server's hostname) []:server.example.com
Email Address []:whatever@server.example.com

Two files are created:

  • certs/myca.crt – This is your CA’s certificate and can be publicly available and of course world readable.
  • private/myca.key – This is your CA’s private key. Although it is protected with a passphrase you should restrict access to it, so that only root can read it:
    # chmod 0400 /etc/pki_jungle/myCA/private/myca.key

More openssl configuration (mandatory)

Because we use a custom directory for our certificates’ management, some modifications to /etc/pki_jungle/myCA/openssl.my.cnf are necessary. Open it in your favourite text editor as root and find the following part (around line 35):

[ CA_default ]

dir     = ../../CA      # Where everything is kept
certs       = $dir/certs        # Where the issued certs are kept
crl_dir     = $dir/crl      # Where the issued crl are kept
database    = $dir/index.txt    # database index file.
#unique_subject = no            # Set to 'no' to allow creation of
                    # several ctificates with same subject.
new_certs_dir   = $dir/newcerts     # default place for new certs.

certificate = $dir/cacert.pem   # The CA certificate
serial      = $dir/serial       # The current serial number
#crlnumber  = $dir/crlnumber    # the current crl number must be
                    # commented out to leave a V1 CRL
crl     = $dir/crl.pem      # The current CRL
private_key = $dir/private/cakey.pem    # The private key
RANDFILE    = $dir/private/.rand    # private random number file

x509_extensions = usr_cert      # The extentions to add to the cert

You should modify the following settings in order to coform to our custom directory and our custom CA key and certificate:

[ CA_default ]

dir     = .                # <--CHANGE THIS
certs       = $dir/certs
crl_dir     = $dir/crl
database    = $dir/index.txt
#unique_subject = no

new_certs_dir   = $dir/newcerts

certificate = $dir/certs/myca.crt   # <--CHANGE THIS
serial      = $dir/serial
#crlnumber  = $dir/crlnumber

crl     = $dir/crl.pem
private_key = $dir/private/myca.key    # <--CHANGE THIS
RANDFILE    = $dir/private/.rand

x509_extensions = usr_cert

Create a Server certificate

Further openssl.my.cnf file’s customization is possible, so that we define our policy for certificate creation and signing or define our desired extensions for the new certificates. I may add this info to a future version of this document. It’s easy though, just try to familiarize yourself with the openssl.cnf’s structure and you’ll figure it out.

Anyway, the certificates we are going to create, without customizing openssl.my.cnf any further, are general purpose certificates and their usage in not restricted to server authentication only. One thing that you should take a note of is that the private keys will not be protected by a passphrase, so that when the services are restarted they do not ask for a passphrase. This means that you should set restrictive permissions on the private keys, so that only root or the user under whose priviledges a server runs can read these files.

Generate a Certificate Request

First, we change to our CA’s directory:

# cd /etc/pki_jungle/myCA/

Then we create the certificate request:

# openssl req -config openssl.my.cnf -new -nodes -keyout private/server.key -out server.csr -days 365

The -nodes option is needed so that the private key is not protected with a passphrase. If you do not intend to use the certificate for server authentication, you should not include it in the above command.
You can customize the number of days you want this certificate to be valid for.

You will be prompted for the certificate’s info. Here is an example:

Country Name (2 letter code) [GB]:GR
State or Province Name (full name) [Berkshire]:Greece
Locality Name (eg, city) [Newbury]:Thessaloniki
Organization Name (eg, company) [My Company Ltd]:My Network
Organizational Unit Name (eg, section) []:My Web Server
Common Name (eg, your name or your server's hostname) []:www.server.example.com
Email Address []:whatever@server.example.com

The Common Name (CN) is the info that uniquely distinguishes your service, so be sure that you type it correctly.
When prompted for some extra attributes (challenge password, optional company name) just hit the [Enter] key.

Two files are created:

  • server.csr – this is the certificate request.
  • private/server.key – this is the private key, which is not protected with a passphrase.

Set restrictive permissions on the private key. Only root or the user that is used to run the server should be able to read it. For example:

# chown root.root /etc/pki_jungle/myCA/private/server.key
# chmod 0400 /etc/pki_jungle/myCA/private/server.key

Or:

# chown root.apache /etc/pki_jungle/myCA/private/server.key
# chmod 0440 /etc/pki_jungle/myCA/private/server.key

Sign the Certificate Request

Now we are going to sign the certificate request and generate the server’s certificate.

First, we change to our CA’s directory:

# cd /etc/pki_jungle/myCA/

Then we sign the certificate request:

# openssl ca -config openssl.my.cnf -policy policy_anything -out certs/server.crt -infiles server.csr

You will need to supply the CA’s private key in order to sign the request. You can check the openssl.my.cnf file about what policy_anything means. In short, the fields about the Country, State or City is not required to match those of your CA’s certificate.

After all this is done two new files are created:

  • certs/server.crt – this is the server’s certificate, which can be made available publicly.
  • newcerts/01.pem – This is exactly the same certificate, but with the certificate’s serial number as a filename. It is not needed.

You can now delete the certificate request (server.csr). It’s no longer needed:

# rm -f /etc/pki_jungle/myCA/server.csr

Verify the certificate

You can see the certificate’s info with the following:

# openssl x509 -subject -issuer -enddate -noout -in /etc/pki_jungle/myCA/certs/server.crt

Or the following:

# openssl x509 -in certs/server.crt -noout -text

And verify that the certificate is valid for server authentication with the following:

# openssl verify -purpose sslserver -CAfile /etc/pki_jungle/myCA/certs/myca.crt /etc/pki_jungle/myCA/certs/server.crt

Server certificate and key in one file

Some servers, for example vsftpd, require that both the private key and the certificate exist in the same file. In a situation like that just do the following:

# cat certs/server.crt private/server.key > private/server-key-cert.pem

You should restrict access to the final file and delete server.crt and server.key since thay are no longer needed.

# chown root.root private/server-key-cert.pem
# chmod 0400 private/server-key-cert.pem
# rm -f certs/server.crt
# rm -f private/server.key

Revoke a Server Certificate

If you do not want a certificate to be valid any more, you have to revoke it. This is done with the command:

# openssl ca -config openssl.my.cnf -revoke certs/server.crt

Then you should generate a new CRL (Certificate Revokation List):

# openssl ca -config openssl.my.cnf -gencrl -out crl/myca.crl

The CRL file is crl/myca.crl.

Distribute your certificates and CRL

Your CA’s certificate and your servers’ certificates should be distributed to those who trust you so they can import them in their client software (web browsers, ftp clients, email clients etc). The CRL should also be published.

Further Reading

As I have said from the beginning, this document is just a summary of what I have read. Here are some useful links that will get you started:

  1. The SSL Certificates HOWTO
  2. The OpenSSL Documentation
  3. The openssl.cnf documentation
  4. OpenSSL Certificate Authority Setup

Be your own Certificate Authority (CA) by George Notaras is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.
Copyright © 2005 - Some Rights Reserved

26 responses on “Be your own Certificate Authority (CA)

  1. Chia Permalink →

    Hi,

    Thanks your document. It helps tremendously.

    Appreciate your effort.

    Best Regards,
    Chia

  2. Marshall Permalink →

    Outstanding.

    Thank you for a concise, complete tutorial. Especially nice is that you create a copy of the original configuration and work with an empty directory hierarchy.

  3. tjl Permalink →

    I thank you also. This was very helpful!

  4. GGeorge Permalink →

    I am interested in knowing whether I can purchase a cetificate and then use it to sign certificates for use by or on behalf of others, for, say, their websites or e-mail services that I am hosting on my servers.

  5. George Notaras Post authorPermalink →

    This is like becoming an official root or intermediate certification authority yourself. I don’t know about the procedures of becoming an official authority, but I don’t think it’s easy, since your root certificate would have to be included in all the major browsers by default. I assume that the latter requires lots of time and money to be spent for building a worldwide trusted company.
    If the root cert not included in the browsers, email clients etc, then it’s like having a self-signed root certificate, which you would have to persuade the whole world to insert it manually to their internet software.

  6. Paritosh Permalink →

    According to the documentation in “http://www.g-loaded.eu/2005/11/10/be-your-own-ca” which are the files that i can use for postfix i.e tls_key_file, tls_cert_file and tls_CAfile.

  7. George Notaras Post authorPermalink →

    Although this information does not belong here, I post it because the postfix configuration is a very good example. So, according to the files that have been generated in the above article, the postfix settings inside the main.cf file that set the paths to the server’s and the certification authority’s certificates are:

    smtp_tls_CAfile = /path/to/certs/myca.crt
    smtp_tls_cert_file = /path/to/certs/server.crt
    smtp_tls_key_file = /path/to/private/server.key
    
    smtpd_tls_CAfile = /path/to/certs/myca.crt
    smtpd_tls_cert_file = /path/to/certs/server.crt
    smtpd_tls_key_file = /path/to/private/server.key
    
  8. Herbie W. Permalink →

    George, thank you very much for creating this. SUPER helpful! Cheers!!!

  9. manish Permalink →

    very helpful document ,
    but i need to know few things
    a) how to ditribute these certificates,i mean i have created my own ca after following these commands, then how to trust and distribute
    b)i have got a server software, i have to put these in that server, how to approach the ca from that server for signing

  10. Jenita Permalink →

    hi,
    write up is informative and helpful,
    thanks.

    cheers,
    jenita.

  11. pmd Permalink →

    Great guide which I followed 5 years ago. Now the CA cert has expired so I think the correct command to extend it for another 5 years is:


    openssl x509 -in certs/EXPIRED-myca.crt -days 1825 -signkey private/myca.key -out certs/NEW-myca.crt

  12. ytifle Permalink →

    Very nice tutorial, very helpful and informative, thanks.

  13. RequiredName Permalink →

    This line:
    openssl ca -config openssl.my.cnf -gencrl -out crl/myca.crl
    requires file: crlnumber

    From some testing – “00” is accepted initial value (0 was invalid)..

  14. Ryan Lopez Permalink →

    Thanks for writing this. It was very clearly written and easy to follow. I was able to setup my CA certs and client/server certs in no time.

    -Ryan

  15. Alia Permalink →

    Thank you for this article. :)
    I have an additional question thou, If I want to create a system that relies on client certificates, what is the best way to distribute those certificates?
    Should these certificates be sent via a web service, or is the only proper way to go by distributing them is through manual distribution and installation in the corresponding certificate stores, without anything programmatic?

    If you know of, or know any sources on best practices in that regard, I would appreciate your help :)

    1. George Notaras Post authorPermalink →

      @Alia: I’m sorry for the delayed reply, but I had missed your comment. I’d probably create a web service, which would first validate the client’s email address and then generate and install the client certificate in their browser and provide instructions or a video about how to back it up.

  16. Daniel Permalink →

    Hello, this certificates are created with RSA, if I want to use ECDSA how can it be done? What are the changes?

    Thanks
    Best Regards

  17. Dennis Permalink →

    Hello there,

    Nice try but it is only valid for one single domain name. If you have many of them and would like to go for example for SAN (subject alternative names) you are stuck. The last command to sign the certificate request is a way too weak and ruins and sends down the drain practically everything that was so nicely and almost perfectly built from the very beginning. I think this last command has to be seriously re-considered / modified. Otherwise, it’s a very nice tutorial for absolute SSL beginners and newbies.

  18. Dave Bauer Permalink →

    Dennis,

    Way to be constructive. Even you concede that the documentation is nice, with only one weakness.

    It is unfortunate that you were unable to actually share what the modification of that last line might look like. On the Internet there are those who contribute and those who do not. You appear to be the later.

  19. Ludvik Permalink →

    @Dennis and Dave :

    I think that if you need SAN (subject alternative names), you are far from being stuck, it still gives you a lot of clues. This document, if it wants to be widely useful, should not elaborate on things that are explained elsewhere and are superfluous. If you are your own certificate authority, you can generate whatever certificates you need for your subdomains, so SAN is, strictly speaking, not so much needed.

    However, I understand that you might want it in certain scenarios, or it could be just a good practice to be able to do this. So let’s see what can be done:

    1) Use Google search for “Openssl Subject Alternative Names” and locate the most promising link. For instance I found this interesting document : “Add an subject alternative name to SSL certificate with openssl”, but there could be more.
    2) It is obvious, that SAN should be dealt with in the moment of generating certificate request. However, we are in the role of both “Server Certificate Requestor” and “Certificate Authority”. The googled documents mostly deals with the role of requestor. From point of view of authority, we probably need to add this ability to our certificate and it would be hard to google this. This should better be found in openssl documentation. I guess this might need to be added to CA configuration before the CA certificate is generated : copy_extensions = copyall , but I could be wrong, so do your own research here.

    Perhaps the best would be to try the whole process without SAN and then with it to resolve separate issues separately, but is should not be a big problem.

  20. Yevgeniy Permalink →

    The best explanation which I have found ever

  21. GM Permalink →

    Hi George Notaras ,
    This post is excellent
    I have one query Basically i am creating CA for my apache server and my android client is communicating using https

    So in apahce which file i need to configure [myca.crt or server.crt] and [myca.key or server.key]
    kindly explain me

    Advance thanks

    1. George Notaras Post authorPermalink →

      Hi GM,

      Thanks for the kind words. I’ll try to briefly explain the logic behind all this.

      The Certificate Authority involves a private key (myca.key) and a public certificate (myca.crt). The Authority’s private key is kept secret and is used to privately sign certificates that are used on various servers (http, ftp, xmpp, webdav, etc). The Authority’s public certificate, which is freely distributed and included in web browsers, in mobile devices etc, is used in order to verify the signature that has been put by the Authority’s private key on the various servers’ certificates.

      So, the Certificate Authority’s private key (myca.key) must be kept in a safe place while its public certificate (myca.crt) should be added to your Android phone. Apache’s private key (server.key) and public certificate (server.crt) must be added to apache.

      In Apache’s mod_ssl configuration you might notice a directive that expects the Certificate Authority’s certificate. This is used for client authentication using PKI and is irrelevant to this use case scenario.

      Hope this helps.

      George

  22. Gerardo L Cahn Permalink →

    Each year, as the self signed certificate of my fedora home server expires, I keep coming back to your blog to read again how to fix it. Thanks again! And Merry Christmas!

    Gerardo

    1. George Notaras Post authorPermalink →

      Gerardo, Thank you very much for your kind words! I’m glad this article has been useful. Merry Christmas!