Creating Your Own SSL Certificate Authority (and Dumping Self Signed Certs)

Jan 11th, 2016: New Year! Also, there was a comment below about adding -sha256 to the signing (both self-signed and CSR signing) since browsers are starting to reject SHA1. Added (I ran through a test, it worked out for me at least).

November 18th, 2015: Oops! A few have mentioned additional errors that I missed. Fixed.

July 11th, 2015: There were a few bugs in this article that went unfixed for a while. They’ve been fixed.

SSL (or TLS if you want to be super totally correct) gives us many things (despite many of the recent shortcomings).

  • Privacy (stop looking at my password)
  • Integrity (data has not been altered in flight)
  • Trust (you are who you say you are)

All three of those are needed when you’re buying stuff from say, Amazon (damn you, Amazon Prime!). But we also use SSL for web user interfaces and other GUIs when  administering devices in our control. When a website gets an SSL certificate, they typically purchase one from a major certificate authority such as DigiCert, Symantec (they bought Verisign’s registrar business), or if you like the murder of elephants and freedom, GoDaddy.  They range from around $12 USD a year to several hundred, depending on the company and level of trust. The benefit that these certificate authorities provide is a chain of trust. Your browser trusts them, they trust a website, therefore your browser trusts the website (check my article on SSL trust, which contains the best SSL diagram ever conceived).

Your devices, on the other hand, the ones you configure and only your organization accesses, don’t need that trust chain built upon the public infrastrucuture. For one, it could get really expensive buying an SSL certificate for each device you control. And secondly, you set the devices up, so you don’t really need that level of trust. So web user interfaces (and other SSL-based interfaces) are almost always protected with self-signed certificates. They’re easy to create, and they’re free. They also provide you with the privacy that comes with encryption, although they don’t do anything about trust. Which is why when you connect to a device with a self-signed certificate, you get one of these: So you have the choice, buy an overpriced SSL certificate from a CA (certificate authority), or get those errors. Well, there’s a third option, one where you can create a private certificate authority, and setting it up is absolutely free.


OpenSSL is a free utility that comes with most installations of MacOS X, Linux, the *BSDs, and Unixes. You can also download a binary copy to run on your Windows installation. And OpenSSL is all you need to create your own private certificate authority. The process for creating your own certificate authority is pretty straight forward:

  1. Create a private key
  2. Self-sign
  3. Install root CA on your various workstations
Once you do that, every device that you manage via HTTPS just needs to have its own certificate created with the following steps:
  1. Create CSR for device
  2. Sign CSR with root CA key
You can have your own private CA setup in less than an hour. And here’s how to do it.

Create the Root Certificate (Done Once)

Creating the root certificate is easy and can be done quickly. Once you do these steps, you’ll end up with a root SSL certificate that you’ll install on all of your desktops, and a private key you’ll use to sign the certificates that get installed on your various devices.

Create the Root Key

The first step is to create the private root key which only takes one step. In the example below, I’m creating a 2048 bit key:

openssl genrsa -out rootCA.key 2048

The standard key sizes today are 1024, 2048, and to a much lesser extent, 4096. I go with 2048, which is what most people use now. 4096 is usually overkill (and 4096 key length is 5 times more computationally intensive than 2048), and people are transitioning away from 1024. Important note: Keep this private key very private. This is the basis of all trust for your certificates, and if someone gets a hold of it, they can generate certificates that your browser will accept. You can also create a key that is password protected by adding -des3:

openssl genrsa -des3 -out rootCA.key 2048

You’ll be prompted to give a password, and from then on you’ll be challenged password every time you use the key. Of course, if you forget the password, you’ll have to do all of this all over again.

The next step is to self-sign this certificate.

openssl req -x509 -new -nodes -key rootCA.key -sha256 -days 1024 -out rootCA.pem

This will start an interactive script which will ask you for various bits of information. Fill it out as you see fit.

You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
Country Name (2 letter code) [AU]:US
State or Province Name (full name) [Some-State]:Oregon
Locality Name (eg, city) []:Portland
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Overlords
Organizational Unit Name (eg, section) []:IT
Common Name (eg, YOUR name) []:Data Center Overlords
Email Address []

Once done, this will create an SSL certificate called rootCA.pem, signed by itself, valid for 1024 days, and it will act as our root certificate. The interesting thing about traditional certificate authorities is that root certificate is also self-signed. But before you can start your own certificate authority, remember the trick is getting those certs in  every browser in the entire world.

Install Root Certificate Into Workstations

For you laptops/desktops/workstations, you’ll need to install the root certificate into your trusted certificate repositories. This can get a little tricky. Some browsers use the default operating system repository. For instance, in Windows both IE and Chrome use the default certificate management.  Go to IE, Internet Options, go to the Content tab, then hit the Certificates button. In Chrome going to Options and Under The Hood, and Manage certificates. They both take you to the same place, the Windows certificate repository. You’ll want to install the root CA certificate (not the key) under the Trusted Root Certificate Authorities tab. However, in Windows Firefox has its own certificate repository, so if you use IE or Chrome as well as Firefox, you’ll have to install the root certificate into both the Windows repository and the Firefox repository. In a Mac, Safari, Firefox, and Chrome all use the Mac OS X certificate management system, so you just have to install it once on a Mac. With Linux, I believe it’s on a browser-per-browser basis.

Create A Certificate (Done Once Per Device)

Every device that you wish to install a trusted certificate will need to go through this process. First, just like with the root CA step, you’ll need to create a private key (different from the root CA).

openssl genrsa -out device.key 2048

Once the key is created, you’ll generate the certificate signing request.

openssl req -new -key device.key -out device.csr

You’ll be asked various questions (Country, State/Province, etc.). Answer them how you see fit. The important question to answer though is common-name.

Common Name (eg, YOUR name) []:

Whatever you see in the address field in your browser when you go to your device must be what you put under common name, even if it’s an IP address.  Yes, even an IP (IPv4 or IPv6) address works under common name. If it doesn’t match, even a properly signed certificate will not validate correctly and you’ll get the “cannot verify authenticity” error. Once that’s done, you’ll sign the CSR, which requires the CA root key.

openssl x509 -req -in device.csr -CA rootCA.pem -CAkey rootCA.key -CAcreateserial -out device.crt -days 500 -sha256

This creates a signed certificate called device.crt which is valid for 500 days (you can adjust the number of days of course, although it doesn’t make sense to have a certificate that lasts longer than the root certificate). The next step is to take the key and the certificate and install them in your device. Most network devices that are controlled via HTTPS have some mechanism for you to install. For example, I’m running F5’s LTM VE (virtual edition) as a VM on my ESXi 4 host. Log into F5’s web GUI (and should be the last time you’re greeted by the warning), and go to System, Device Certificates, and Device Certificate. In the drop down select Certificate and Key, and either past the contents of the key and certificate file, or you can upload them from your workstation.

After that, all you need to do is close your browser and hit the GUI site again. If you did it right, you’ll see no warning and a nice greenness in your address bar.

And speaking of VMware, you know that annoying message you always get when connecting to an ESXi host?

You can get rid of that by creating a key and certificate for your ESXi server and installing them as /etc/vmware/ssl/rui.crt and /etc/vmware/ssl/rui.key.

61 Responses to Creating Your Own SSL Certificate Authority (and Dumping Self Signed Certs)

  1. Thank you for this. I’ve wanted to do this for quite a while but never bothered to look into what was needed.

    Also, I think “convinced” in “best SSL diagram ever convinced” was meant to be “conceived”. And yes, it is an awesome diagram.

  2. If you do not want to remember all the openssl command line arguments you could use a GUI such as

  3. gillespiem says:

    Good article (and great graphics), but the title is misleading.

    In no way does this dump self-signed certs as “(and Dumping Self Signed Certs)” claims – by definition a self-signed cert is “signed by the same entity whose identity it certifies”.

    You’re simply installing a root certificate soas to prevent clients from prompting you to acknowledge the certificate isn’t verified. It’s still very helpful, but it’s not dumping self-signed certs in any form.

  4. j says:

    The next step is to self-sign this certificate.

    openssl req -x509 -new -nodes -key root.key -days 1024 -out rootCA.pem

    …did you mean rootCA.key?

    anyways this looks great, look forward to giving it a try

  5. Neddage says:

    Good article. What’s the procedure when the root CA expires? Do you need to update all the other servers certificates or is there a shortcut? Or should you just give the root CA a lot longer before it expires, say 5 years?

    • tonybourke says:

      Yeah, if the root expires, everything needs to be updated. That’s why if you look at root certificates in your operating system, they usually expire in 10-30 years.

  6. Joe says:

    What do you to update the rootCA bit size from 1024 to 2048? Do you reissue or can you just update the bit size?

    • dthompson says:

      The example is already 2048 bits for both root and “device”. But if you already have 1024 and want to change to 2048, which is a good idea, yes you must generate new keys and new certs. You can use the same name for the device or other end-entity certs (unless you WANT to change) but you should use a different name for the root cert to prevent a verifier from getting confused about which root is the right one and giving security errors that 99.99% of users won’t understand. (Even getting “root not found” many users won’t understand, but at least it points them in the right direction.)

  7. Pingback: Confluence: ELSTER

  8. Pingback: Confluence: ELSTER

  9. Here’s a tip: If you create a CA, don’t store the private key on a github repository.

    If I have a group of machines at work that will accept any device certificates signed by my CA, I don’t want someone using that CA key to potentially sign a proxy certificate or some other spoof.

  10. Julius says:

    A little improved security, adapted to post-Snowden knowledge:
    – Install the absolute latest version of openssl (bypass apt or yum, use source..).
    – Fine commands to use instead of the two mentioned in your article:

    # openssl genrsa -out /root/rootCA.key 4096 -aes-256-cbc

    # openssl req -x509 -new -nodes -key /root/rootCA.key -days 3650 -out rootCA.pem -config /etc/ssl/openssl.cnf

    And you can edit the openssl.cnf defaults under [ req_distinguished_name ] to save time..

  11. Alex says:

    Good article, I am just missing or not understanding something.

    I am in a client server situation.
    I guess I put the rootCA.pem on the server and the device.crt on the client but that doesnt seem enough to me.
    Dont I need to create a server certificate, generate a public part, and put that public part in the client?
    If yes, how do I generate that?

    But what do I put on the client app?

    • ychaouche says:

      If I understood correctly, nothing is to be installed on the client (the browsers) except the root certificate.

      To recap :
      1. You need an SSL key for your server
      2. The SSL key must be signed by a certificate authority
      3. You have two choices : a) buy a certificate by already existing authorities like Verisign or b) become an authority yourself. The article describes b)
      4. So you create what’s called a root certificate. A root certificate is a certificate that belongs to the top node of the trust hierarchy.
      5. Next, you create certificates for any of your servers (referred to as devices in this article) that need / want to have an SSL encryption (HTTPS URLs or mail servers with TLS encryption)
      6. Sign every single certificate with the root certificate you created at step 4.
      7. Deploy the certificates to their belongers (your HTTPS servers or mail servers)
      8. When you browse to these servers you will still get an SSL error because your servers’ certificates are authenticated by a certificate authority that your browser doesn’t know. So step 9
      9. is to install the root certificate in every browser that needs to access your servers, that way browsers will trust the certificates issued (signed) by that root certificate you’ve created.

      Mistakes, if any, are mine.

      • Edd says:

        How to install the root CA on the browsers? is necesary did the 8 steps before i can install the rootCA in the browsers?

    • Alan says:

      I am replying directly to this post, as ychaouche’s response is still slightly ambiguous.

      The rootCA.pem file is installed in the browser. That allows it to recognise the response made by the server using the device.crt file.

      You install both the device.key file (the private key) and the device.crt file (the public key signed by the rootCA) on the server. Depends what server you have where you put the files but they are normally called ssl_certificate and ssl_certificate_key (thats the nginx directives) or something like that for apache. nodejs(https) uses a cert object {key: xxx cert: yyy} where you read the filecontents of the key and certiciate and load them into the strings xxx and yyy.

  12. Simply the best and most straightforward article on the interwebs on this overly complex subject. Thank you.

  13. -des3 must come earlier, otherwise it’s ignored. at least on my Debian version (OpenSSL 1.0.1e 11 Feb 2013) it is.

    openssl genrsa -des3 -out rootCA.key 2048

    • FYI, this is what i ended up with (note the various encryption and hash choices):

      the ca itself:
      openssl genrsa -aes256 -out $CA_NAME.key 4096
      openssl req -x509 -sha512 -new -nodes -key $CA_NAME.key -days 65000 -out $CA_NAME.pem

      a site certificate:
      openssl genrsa -out $FQDN.key 2048
      openssl req -sha512 -new -key $FQDN.key -out $FQDN.csr
      openssl x509 -sha512 -req -in $FQDN.csr -CA $CA_NAME.pem -CAkey $CA_NAME.key -CAcreateserial -out $FQDN.crt -days 65000

      install the root ca into a linux:
      cp rootCA.pem /usr/local/share/ca-certificates/rootCA.crt # with .crt extension!!!

      • dthompson says:

        Yes, -des3 (or another cipher like -aes128) must come before the bitsize on genrsa; it may be before or after -out file.

        OTOH, for now I wouldn’t recommend -days 65000. I’m pretty sure there are still fielded systems checking cert times using 32-bit time_t and getting Y2038 bugs; that means about 8700 days from now (and going down steadily). Also, unfortunately, not all Linux distros, versions, or packages put openssl’s default store in the same place. Use ‘openssl version -d’ (or -a) to see where yours is. And I’m not sure they all have update-ca-certificates; you may have to run c_rehash yourself.

  14. Pingback: cephalin

  15. Hi. Does this process work for wildcards? Or do I have to create a new set of certificates for each sub-domain. Ideally, I’d create one for each domain. Thx.

  16. Pingback: Confluence: Technische Dienst

  17. Pingback: Skapa ett självsignerat certifikat till Synology Diskstation med OpenSSL | Jonatan Hilmarch

  18. Pingback: AFNetworking problems with TLS Verification of a self signed server root CA - BlogoSfera

  19. Gareth says:

    hi. regarding Deprecation of Internal Server Names and Reserved IP Addresses –

    Any idea? but we have hotspots that require a private IP and the controller can hold a self-signed CA cert that is used with the SSL HTML handshake (common name = private IP), between client and access point, but, we don’t/can’t load the CA cert onto joe public and currently they get a warning message, will they still be able to negate the warning after next years deadline date?

  20. Sean says:

    Add -sha256 to signing commands to create certificates with SHA256 signed certificates so browsers won’t reject them. SHA1 deprecated.

  21. BP SF says:

    This totally worked! I’m seriously super stoked… thanks a ton!

  22. Edd says:

    how i can install the root CA in a browser on a Windows machine.???

  23. Jeff says:

    Re: For Apache 2.2 on RH 6.5 I get this error: SSLCertificateKeyFile: file ‘/etc/pki/tls/private/device.key’ does not exist or is empty.

  24. Costas says:

    With cPanel I am also being asked for “Certificate Authority Bundle” in addition to the key and certificate. Is it possible to have self certified certificates on cPanel hosts?

  25. Costas says:

    Not sure if my last post is still pending approval but I didn’t see any notice so I am posting again.
    I tried your system on a cPanel hsoted server and it is asking for the Certificate Authority Bundle for the certificate. Is it not possible to add self signed certificates to cPanel hosts?

  26. Pankaj Chhabra says:

    How to generate intermed certificate?

  27. Pingback: SSL certificates - can they be used on more than one server * VPN SSL Online

  28. Pingback: Confluence: Production Engineering

  29. Would you also know how to create an end entity certificate with OpenSSL?

  30. ellayaraja says:

    Once I have created Self Sign certificate in Trusted Root Certificates, How to we access this from c# to make web http request? If any one know helps me.

  31. jolly says:

    I need to try this hope it work for me i really want to have this SSL.

    Thanks for Sharing.

  32. Pingback: Creating an SSL Certificate Authority (CA), signing certificates and authenticating using a client certificate | Squirrel5 – Linux Systems Administration services

  33. Renato Oliveira says:

    Thak you! Great post!

  34. anonymous says:

    Thank you very much. This helped me a lot

  35. farhanahmad123 says:

    Great article. Just a small thing, If I am generating certs for clients also, then client.crt and client.key will be at client side, and on server? will only rootca.pem in truststore will be enough? since client certs are signed with rootca or do i need to copy client.crt on server to make it work?

  36. Online says:

    How to generate intermediate certificate here with root?

  37. errornosignal says:

    Excellent tutorial!

  38. Billy says:

    OpenSSL is creating a .pem cert. Chrome will not recognize it.

  39. tonsofsteel says:

    OpenSSL is creating a .pem cert. Chrome won’t recognize it…

  40. Gaurav says:

    Great explanation.
    One more thing i just wanted to know, if i update the CA certificate using different RSA key (2096) and keeping all information same and authorize my client certificate using that, now if i update the CA certificate to server and trying to authenticate the client it is failing. Error 20 no local issue CA certificate for the client. I require a server restart before authenticating using new CA and User certificate, why a server restart is require?


  41. lactus says:

    Great article.
    But after installing rootCA.pem in firefox, i get SEC_ERROR_INADEQUATE_KEY_USAGE and no option to allow the certificate.
    Without installing the rootCA, i get only SEC_ERROR_UNKNOWN_ISSUER, this should be normal for selfsigned certs

    Are there any limitations in filling the forms other than the common name? May I use the same values?

    • lactus says:

      Problem was in openssl.cnf:
      keyUsage must include cRLSign and keyCertSign

      keyUsage = cRLSign, keyCertSign

  42. Andrej says:

    Is it possible to create a v3 certificate with the last command?

  43. This looks good if you control the browser, in case where i have a site and people around the world buy stuff from my site. I dont control their browsers, why would they listen to my instructions to setup their browsers to install the certificate? Not sure if I am missing something.

    • tonybourke says:

      You are correct. For users you don’t know, a typical certificate would be appropriate. This is for the situation where you control the gear and you control the browser, and wanting to use the trust aspect of SSL without paying a certificate authority.

      An example would be the user interface on an F5 load balancer or even your home Wifi router. You want to use encryption, but you get that “warning” every time you hit the site because while the communication is encrypted, it’s not “trusted”. This allows you to do trust (and at the very least, get rid of that annoying error message).

  44. mmangosoft says:

    Thank you very much! Great article. I have just generated a set of self-signed certificates.

  45. David Zapata says:

    I have executed all steps as explained, although I have a doubt with the final result: Shouldn’t the final device.crt, when checking it’s details, show a certification path where the root id the CA certificate we created first? I did all steps and the final device.crt only shows itself in the certification path. Is this OK?

  46. Jane Mary says:

    Hi, thanks for this nice step-by-step tutorial. I just did a thing like this in a company network, and I just want to add that when it comes to root certificate deployment, Firefox has an option to use the system’s certificate repository as well. (Windows 7 in my case.)
    In Firefox’s about:config, find a key named security.enterprise_roots.enabled and set it to True (False by default).
    That said, it should “just work” on most setups. Maybe you need to flush an individual system’s browser and/or dns cache first (as in “when was the last time you shut down your computer?” – “errrmmm, dunno… February?”), but all in all, it worked surprisingly well on a multitude of years-old Windows setups.

  47. New browser requirements involve san: Subeject Alternative Naming. Can you add where that process fits in your guide and how to meet those requirements?

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: