[Nov 17, 2015: the article is updated to follow modern security requirements for SSL certificates]
This article explains how to create your own Certificate Authority and create the SSL certificates signed by this authority. While there is a lot of articles which talk about how to create your own SSL certificates, in most cases they describe how to create self-signed certificates. It is simpler, but those certificates cannot be verified or tracked. Personally I prefer to create the personal Certificate Authority (CA) first and then issue the certificates from this authority. The main advantage of this approach is that you can import the certificate of your CA into your browser or your cell phone, and you won’t get any more warnings when accessing your own web site or connecting to SMTP/IMAP server as your certificate is now considered trusted. This is also necessary if you create the certificate hierarchy for your own project and want to be the only one who can issue the certificates for the users.
This post assumes you have the OpenSSL toolkit installed, and openssl command-line utility is working properly.
Creating the Certificate Authority configuration
Create the directory on your disk, and save the following configuration file there under the name ca.cnf. You can edit the parameters marked as “EDIT THOSE”, and you can change some parameters (for example, if you want your certificates to be valid for longer than one year you can change the default_days), but the defaults should be good enough for the vast majority of users
[ ca ] default_ca = mypersonalca [ mypersonalca ] # # WARNING: if you change that, change the default_keyfile in the [req] section below too # Where everything is kept dir = ./mypersonalca # Where the issued certs are kept certs = $dir/certs # Where the issued crl are kept crl_dir = $dir/crl # database index file database = $dir/index.txt # default place for new certs new_certs_dir = $dir/certs # # The CA certificate certificate = $dir/certs/ca.pem # The current serial number serial = $dir/serial # The current CRL crl = $dir/crl/crl.pem # WARNING: if you change that, change the default_keyfile in the [req] section below too # The private key private_key = $dir/private/ca.key # private random number file RANDFILE = $dir/private/.rand # The extentions to add to the cert x509_extensions = usr_cert # how long to certify for default_days = 365 # how long before next CRL default_crl_days= 30 # which message digest to use default_md = sha256 # keep passed DN ordering preserve = no # Section names policy = mypolicy x509_extensions = certificate_extensions [ mypolicy ] # Use the supplied information commonName = supplied stateOrProvinceName = supplied countryName = supplied emailAddress = supplied organizationName = supplied organizationalUnitName = optional [ certificate_extensions ] # The signed certificate cannot be used as CA basicConstraints = CA:false [ req ] # same as private_key default_keyfile = ./mypersonalca/private/ca.key # Which hash to use default_md = sha256 # No prompts prompt = no # This is for CA subjectKeyIdentifier=hash authorityKeyIdentifier=keyid:always,issuer string_mask = utf8only basicConstraints = CA:true distinguished_name = root_ca_distinguished_name x509_extensions = root_ca_extensions [ root_ca_distinguished_name ] # EDIT THOSE commonName = My Personal CA stateOrProvinceName = California countryName = US emailAddress = certs@example.com organizationName = My Personal Certification Authority [ root_ca_extensions ] basicConstraints = CA:true
Then create the directory structure which will be used by your CA. This assumes you did not change the directory name in the configuration file above:
# mkdir -p mypersonalca/certs # mkdir -p mypersonalca/private # mkdir -p mypersonalca/crl # echo "01" > mypersonalca/serial # touch mypersonalca/index.txt
Generating the Certificate Authority private key and certificate
To generate the Certificate Authority with a 2048 bit private key and with the certificate which is valid for ten years (3650 days) execute the following command:
OPENSSL=ca.cnf openssl req -x509 -nodes -days 3650 \ -newkey rsa:2048 -out mypersonalca/certs/ca.pem \ -outform PEM -keyout ./mypersonalca/private/ca.key
It will ask you the questions about the information which will be embedded into your CA certificate. Answer meaningfully so when you can see this certificate in your browser you wouldn’t wonder what it is about.
Once the command above is completed you should have two files: mypersonalca/certs/ca.pem and mypersonalca/private/ca.key. The key file must be kept in secret. Anyone who gets the ca.key will be able to sign the certificates for your CA. The ca.pem file is your public CA certificate which could be imported into your browser or mobile platform to make your root CA recognizable by the device.
Now you have the CA key you can start generating and signing the certificates.
Generating the certificate
The process of getting a valid certificate consists of two phases. First the certificate is generated, and then it is signed by your CA.
The following command is used to generate the certificate and the 1024-bit private key:
openssl req -newkey rsa:1024 -nodes -sha256 \ -keyout cert.key -keyform PEM -out cert.req -outform PEM
This command will ask you a few questions about the certificate issuer. This information will be visible to anyone who connects to your server. If you create the SSL certificate for your web or mail server, pay special attention to the Common Name field. You must enter there the fully-qualified domain name this certificate will serve. For example, if your web server is https://mymail.example.com your common name must be mymail.example.com. You can also use the wildcard in the first part of the domain name: a certificate with the common name such as *.example.com could be used for all subdomains of the example.com. An e-mail address must also be supplied, although it doesn’t have to be valid.
Signing the certificate by the CA
Once the certificate is created it needs to be signed by your CA to be recognizable:
OPENSSL_CONF=ca.cnf openssl ca -batch -notext -in cert.req -out cert.pem
Now you got the pair: the signed certificate cert.pem and the corresponding private key, cert.key which you can use as needed.
Printing the certificate parameters
Once in a while you may want to peek inside a specific certificate to see what’s inside. The following command will print the content of the cert.pem certificate:
openssl x509 -in cert.pem -noout -text
The important fields in the output are the following:
- Issuer (information about the CA which signed the certificate)
- Subject (information about the entity which uses the certificate)
- Validity (time period when the certificate is valid)
That’s it. Now you can generate the certificates signed by your own CA!
I’d rather put
“# Which hash to use
default_md = sha1”
in the ca.cnf, since browsers now assume that md5 in not trusty enough anymore.
For example, in chromium I get a warning like “The site’s security certificate was signed with a weak signature algorithm.” because I used md5 to sign the certificate.
The first line should be changed also:
# which md to use
default_md = sha1
(btw it is the most important line)
Fixed. Thank you!
When creating the directory structure it should be # mkdir -p mypersonalca/crl. You have # mkdir -p mypersonalca/crt.
Also, when generating the certificate authority shouldn’t it start out with OPENSSL_CONF=ca.crt as you have in the section on generating a certificate?
I think yes.
I don’t see it. There is OPENSSL_CONF=ca.crt in generating the certificate authority, and there is no such thing in generating the certificate (nor it should be). Could you please point out to a specific item?
I had an issue when i was trying to generate a self signed CA cert with a conf file with default_md = sha1 under [ mypersonalca ]. It was not generating the cert with SHA1 because i had default_md = MD5 under [req]. So please make sure to change default_md =sha1 under [req] to have your CA cert generated with SHA-1 algorithm.
Please excuse my ignorance, but when generating the Certificate Authority and Key, is this done in basic command line or in the Openssl command window? I’ve tried the code in both and get errors. Any dumding down for the layman here would be “GREATLY” appreciated. Thanks in Advance.
Everything in this article is done in command line. Preferably in Cygwin shell (assuming you run Windows) as some operations might fail in “basic” command line shell.
Have you ever tried to create the CA using Public wildcard Security Certificate from Godaddy, Thwate, or some other verified source? I have several servers on my domain, Java email server, ISS and DNN, and and I am looking at adding a Linux file server. Setting up the wildcard in any of the servers and exporting out to formats the other servers use has been a disaster. My thinking is it is best to bring the wildcard cert into a program that is designed to create and issue certificated in different formats.
I have self-signed the wildcard certificate, works as usual.
Pingback: Setup Your Own Certificate Authority (CA) on Linux and Use it in a Windows Environment | VirtuallyHyper
I think there is a mistake in the configuration file (“ca.cnf”) – prompts is set to “no”, when it should probably be set to “yes”. Without prompts, you don’t get to enter CA information, such as the common name.
Prompts are set to no only for [req] – i.e. signing the requests.
I am trying to use the steps above on my linux box.
OPENSSL=ca.cnf: Command not found.
do i need to add anything to make this work?
You probably don’t have openssl installed.