For the purposes of testing certain types of process over https, it is useful to be able to create certificate signing request and have them signed by a trusted certificate authority and be able to generate certificates for local test sites at will.
This is where a personal root CA can be used. I had a recent project developing some web services where I wanted a client to present a signed certificate trusted by the server before being allowed to upload its set of JSON data.
There’s no getting away from the fact that setting up a CA for the first time is hard. It will take time and it shouldn’t be expected to work first time; it took me three attempts, can be very difficult to troubleshoot and diagnose, and can be easier to start from scratch than try to fix.
My primary guide for setting up the CA structure cn be found at  and is clearly written and easy to follow although still missing some crucial details that are more important now than when the article was originally produced.
This guide suggested setting a distinct root CA that signs the certificate for an intermediate CA that is actually used to sign the client and server certificates. While a bit more work is involved I liked the approach.
The basic steps are
$ mkdir root-ca $ cd root-ca $ mkdir certs crl newcerts private $ chmod 700 private $ touch index.txt $ echo 1000 > serial
To create a configuration specific to the root CA, copy https://jamielinux.com/docs/openssl-certificate-authority/_downloads/root-config.txt
to root-ca-openssl.conf amending the top level dir entry as appropriate.
$ openssl genrsa -aes256 -out private/ca.key.pem 4096
$ chmod 400 private/ca.key.pem
Enter the private key passphrase and answer the questions
$ openssl req -config root-ca-openssl.conf \ -key private/ca.key.pem \ -new -x509 -days 7300 -sha256 -extensions v3_ca \ -out certs/ca.cert.pem Enter pass phrase for private/ca.key.pem:
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) [GB]: State or Province Name [England]:Myland Locality Name :Mylocal Organization Name [Alice Ltd]:Org Services Organizational Unit Name :Org Services Root CA Common Name :root-ca.localdomain Email Address :root-ca@localhost $ chmod 444 certs/ca.cert.pem
Verify the certificate
$ openssl x509 -noout -text -in certs/ca.cert.pem
This certificate can now ben used to sign the intermediate CAs request.
Create the intermediate pair, signed by the root, but used to sign the issued
certs on behalf of the root.
$ mkdir intermediate-ca $ cd intermediate-ca $ mkdir certs crl csr newcerts private $ chmod 700 private $ touch index.txt $ echo 1000 > serial $ echo 1000 > crlnumber $ echo "unique_subject = no" > index.txt.attr - see  $ cp ../root-ca/root-ca-openssl.conf intermediate-openssl.conf
Make the following changes to the conf file:
[ CA_default ] dir = /root/ca/intermediate private_key = $dir/private/intermediate.key.pem certificate = $dir/certs/intermediate.cert.pem crl = $dir/crl/intermediate.crl.pem policy = policy_loose
Now generate the intermediate key
$ cd intermediate-ca $ openssl genrsa -aes256 \ -out private/intermediate.key.pem 4096 $ openssl req -config intermediate-openssl.conf -new -sha256 \ -key private/intermediate.key.pem \ -out csr/intermediate.csr.pem Enter pass phrase for private/intermediate.key.pem: 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) [GB]: State or Province Name [England]:Myland Locality Name :Mylocal Organization Name [Alice Ltd]:Org Services Organizational Unit Name :Org Services Intermediate CA Common Name :intermediate-ca@localdomain Email Address :intermediate-ca@localhost
When creating the certificate, use the root ca openssl configuration
$ openssl ca -config ../root-ca/root-ca-openssl.conf -extensions v3_intermediate_ca \ -days 3650 -notext -md sha256 \ -in csr/intermediate.csr.pem \ -out certs/intermediate.cert.pem Check that the request matches the signature Signature ok Certificate Details: ... Certificate is to be certified until Nov 26 21:57:04 2026 GMT (3650 days) Sign the certificate? [y/n]:y 1 out of 1 certificate requests certified, commit? [y/n]y Write out database with 1 new entries Data Base UpdatedCertificate is to be certified until Nov 26 21:57:04 2026 GMT (3650 days) Sign the certificate? [y/n]:y 1 out of 1 certificate requests certified, commit? [y/n]y Write out database with 1 new entries Data Base Updated $ chmod 444 certs/intermediate.cert.pem
Check that the root CA index.txt file contains an entry like,
$ more ../root-ca/index.txt V 263326226815P 1000 unknown /C=GB/ST=Myland/O=Org Services/OU=Org Services Certificate Authority/CN=Org Services Intermediate CA
Verify the certificate and the chin of trust
$ openssl x509 -noout -text -in certs/intermediate.cert.pem $ openssl verify -CAfile ../root-ca/certs/ca.cert.pem certs/intermediate.cert.pem certs/intermediate.cert.pem: OK
Create a certificate chain so that clients can verify the intermediate against
the root certificate,
$ cat certs/intermediate.cert.pem ../root-ca/certs/ca.cert.pem > certs/ca-chain.cert.pem $ chmod 444 certs/ca-chain.cert.pem
The final part of preparing the CA for use is to add a section to the intermediate openssl configuration that includes Subject Alternate Name (SAN) entries, something similar to,
[ alternate_names ] DNS.1 = inventory-master.localdomain DNS.2 = *.inventory-master.localdomain [ v3_req ] basicConstraints = CA:FALSE keyUsage = nonRepudiation, digitalSignature, keyEncipherment subjectAltName = @alternate_names ... [req] ... req_extensions = v3_req
Although there is much scope in the other options for requests, so long as ‘subjectAltName’ resolves then the configuration is good.
I will describe the detail of setting up a web server to make use of the CA in another page soon.
In no particular order (of preference or usefulness) I found the following resources helpful in developing my working system.
 https://jamielinux.com/docs/openssl-certificate-authority/ – an excellent
guide except that it is missing the need to use SubjectAlternateNames.
 https://pypi.python.org/pypi/blitz-ca/0.1.1 – Python local CA; not used here
 http://wiki.cacert.org/FAQ/subjectAltName – Adding SubjectAltName to a cert
 http://apetec.com/support/generatesan-csr.htm – for creating SAN server
certificates (even though the cert creation command is missing a space in the
 http://stackoverflow.com/questions/21488845/how-can-i-generate-a-self-signed-certificate-with-subjectaltname-using-openssl – gives a good description; ignore the off-topic moan; it is directly related to programming as I can testify in this example.
 http://serverfault.com/questions/721572/nginx-verifying-client-certs-only-on-a-particular-location – Location-based authorisation so that CSRs and heartbeats can be processed without requiring a cert;
 https://support.globalsign.com/customer/portal/articles/1353601-converting-certificates—openssl – Converting certs and keys from one format to another. Lots of sites will do this
 https://kb.wisc.edu/middleware/page.php?id=4064 – Verifying that a certificate and key match.
 http://stackoverflow.com/questions/9496698/how-to-revoke-an-openssl-certificate-when-you-dont-have-the-certificate – How to get past certificate database errors when re-requesting a replacement
 http://stackoverflow.com/questions/7885785/using-openssl-to-get-the-certificate-from-a-server – Getting openssl to report the certificates in use on a server. This is hugely useful and should be included as a key validity test. I was at the point of giving up when trying this show an invalid cert chain on the server.
Perhaps a better guide to correctly setting up root CA to self-sign trusted certs
Another problem that can occur when using openssl to diagnose http 400 errors
 http://pages.cs.wisc.edu/~zmiller/ca-howto/ – General root CA setup