There are many blogs and tutorials with nice shortcuts providing the necessary
openssl commands to create and sign x509 certficates.
However, there is precious few instructions for how to easily create your own
certificate authority.
You probably never want to do this in a production environment, but in a
development environment it will make your life signficantly easier.
Create the certificate authority
Create the key and certificate
Pick a directory to store things in. Then, make your certificate authority key and certificate:
openssl genrsa -out cakey.pem 2048
openssl req -x509 -new -nodes -key cakey.pem -sha256 -days 1024 -out cacert.pem
Some tips:
- You will be prompted to enter some information about your certificate
authoirty. Provide the minimum information - i.e., only overwrite the
defaults. So, provide a value for
Country, State or Province, and
Organization Name and leave the rest blank.
- You probably want to leave the password blank if this is a
development/testing environment.
Want to review what you created?
openssl x509 -text -noout -in cacert.pem
Prepare your directory
You can create your own
/etc/ssl/openssl.cnf file and really customize things. But I
find it safer to use your distribution's default file so you can benefit from
changes to it every time you upgrade.
If you
do take the default file, you may have the
dir option coded to
demoCA (in Debian at least, maybe it's the upstream default too).
So, to avoid changing any configuration files, let's just use this value. Which
means... you'll need to create that directory. The setting is relative - so you
can create this directory in the same directory you have your keys.
mkdir demoCA
Lastly, you have to have a file that keeps track of your certificates. If it
doesn't exist, you get an error:
touch demoCA/index.txt
That's it! Your certificate authority is ready to go.
Create a key and ceritificate signing request
First, pick your domain names (aka "common" names). For example,
example.org
and
www.example.org.
Set those values in an environment variable. If you just have one:
export subjectAltName=DNS:example.org
If you have more then one:
export subjectAltName=DNS:example.org,DNS:www.example.org
Next, create a key and a certificate signing request:
openssl req -new -nodes -out new.csr -keyout new.key
Again, you will be prompted for some values (country, state, etc) - be sure to
choose the same values you used with your certficiate authority! I honestly
don't understand why this is necessary (when I set different values I get an
error on the signing request step below). Maybe someone can add a comment to
this post explaining why these values have to match?
Also, you must provide a common name for your certificate - you can choose the
same name as the altSubjectNames value you set above (but just one domain).
Want to review what you created?
openssl req -in new.csr -text -noout
Sign it!
At last the momenet we have been waiting for.
openssl ca -keyfile cakey.pem -cert cacert.pem -out new.crt -outdir . -rand_serial -infiles new.csr
Now yu have a new.crt and new.csr that you can install via your web browser,
mail server, etc specification.
Sanity check it
This command will confirm that the certificate is trusted by your certificate
authority.
openssl verify -no-CApath -CAfile cacert.pem new.crt
But wait, there's still a question of trust
You probably want to tell your computer or browser that you want to trust your
certificate signing authority.
Command line tools
Most tools in linux by default will trust all the certificates in
/etc/ssl/certs/ca-certificates.crt. (If that file doesn't exist, try
installing the
ca-certificates package). If you want to add your certificate
to that file:
cp cacert.pem /usr/local/share/ca-certificates/cacert.crt
sudo dpkg-reconfigure ca-certificates
Want to know what's funny? Ok, not really funny. If the certificate name ends
with
.pem the command above won't work. Seriously.
Once your certificate is installed with your web server you can now test to
make sure it's all working with:
gnutls-cli --print-cert $domainName
Want a second opinion?
curl https://$domainName
wget https://$domainName -O-
Both will report errors if the certificate can't be verified by a system
certificate.
If you really want to narrow down the cause of error (maybe reconfiguring
ca-certificates didn't work)?
curl --cacert /path/to/your/cacert.pem --capath /tmp
Those arguments tell curl to use your certificate authority file and not to
load any other certificate authority files (well, unless you have some
installed in the temp directory).
Web browsers
Firefox and Chrome have their own store of trusted certificates - you'll have
to import your cacert.pem file into each browser that you want to trust your
key.