Setting up your own, private CA may be useful in several scenarios. I was setting up my own Kubernetes cluster and that needed a docker registry. The docker requires SSL and in my setup, a private CA made the most sense.
The openssl package brings a script, that implements a CA. The script is called CA.pl and is part of the openssl packages (on Ubuntu and probably everywhere else).
CA.pl is a script and has a few configurations in itself. I copied the script from /usr/lib/ssl/misc/CA.pl into my ~/bin directory and changed the name of the CA top directory:
my $CATOP = "./joergsCA";
also, I changed the default time a certificate is valid from 3 years to forever (100 years – which is probably the same as forever).
my $CADAYS = "-days 36500"; # 100 years
I create the ca in a directory in my home: ~/ca/ . From here, I called
and got a new directory ~/ca/joergsCA and a few more files, after answering a few questions. The first question is the passphrase, which belongs into your password safe.
- cacert.pem is the public certificate (you may share that with the world)
- private/cakey.pem is the private key, that you need to keep secret.
This ca certificate is not yet known to my machine. No program would use the certificate to validate anything. For that you need to do 2 things:
- copy the public part of the cert to a well known place, the system certificate store. For Ubuntu it’s “/usr/local/share/ca-certificates/”
- update the cerficate list on the machine
joerg@store: cp joergsCA/cacert.pem /usr/local/share/ca-certificates/joergsca.crt joerg@store: sudo dpkg-reconfigure ca-certificates
From here on, I mostly worked out of the ~/ca directory. If you execute “CA.pl -newreq”in this directory, then it creates a new certificate request that needs to be signed with “CA.pl -sign”.
joerg@store:~/ca$ CA.pl -newreq Use of uninitialized value $1 in concatenation (.) or string at /home/joerg/bin/CA.pl line 134. ==== openssl req -new -keyout newkey.pem -out newreq.pem -days 365 Generating a 2048 bit RSA private key ................................+++ ................................................................................................................................+++ unable to write 'random state' writing new private key to 'newkey.pem' Enter PEM pass phrase: Verifying - Enter PEM pass phrase: ----- 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) [DE]: State or Province Name (full name) [Germany]: Locality Name (eg, city) [Karlsruhe]: Organization Name (eg, company) [joergbeyer.com]: Organizational Unit Name (eg, section) : Common Name (e.g. server FQDN or YOUR name) :drucker.fritz.box Email Address : Please enter the following 'extra' attributes to be sent with your certificate request A challenge password : An optional company name : ==> 0 ==== Request is in newreq.pem, private key is in newkey.pem joerg@store:~/ca$ CA.pl -sign ==== openssl ca -policy policy_anything -out newcert.pem -infiles newreq.pem Using configuration from /usr/lib/ssl/openssl.cnf Enter pass phrase for ./joergsCA/private/cakey.pem: Check that the request matches the signature Signature ok Certificate Details: Serial Number: fc:28:99:c9:55:d3:5d:f8 Validity Not Before: Jan 5 17:18:40 2019 GMT Not After : Jan 5 17:18:40 2020 GMT Subject: countryName = DE stateOrProvinceName = Germany localityName = Karlsruhe organizationName = joergbeyer.com commonName = drucker.fritz.box X509v3 extensions: X509v3 Basic Constraints: CA:FALSE Netscape Cert Type: SSL Server X509v3 Key Usage: critical Key Encipherment X509v3 Extended Key Usage: TLS Web Server Authentication Netscape Comment: OpenSSL Generated Certificate X509v3 Subject Key Identifier: D8:E9:91:07:EA:71:E3:00:75:FE:0C:FC:2A:1F:EE:DA:3B:4F:D3:D8 X509v3 Authority Key Identifier: keyid:72:B4:4B:73:4C:04:76:8A:43:BC:8C:3C:0E:BC:BE:C3:6E:7F:01:AA X509v3 Subject Alternative Name: DNS:*.fritz.box, DNS:*.joergbeyer.com Certificate is to be certified until Jan 5 17:18:40 2020 GMT (365 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 unable to write 'random state' ==> 0 ==== Signed certificate is in newcert.pem
now you have the public certificate “newcert.pem” and the private “newkey.pem”. Let’s move them to a permanent place:
joerg@store:~/ca$ openssl rsa -in newkey.pem -out joergsCA/private/drucker.pem Enter pass phrase for newkey.pem: writing RSA key joerg@store:~/ca$ mv newcert.pem joergsCA/certs/drucker_cert.pem
with the first step, I also remove the passphrase from the private key.
I will use the freshly create certificate for my printer (“drucker” is german for “printer”). I own a Canon Maxify printer. In it’s web menu, under “Security”, you can upload a combined file with contains the private and the public part of the certificate. The printer needs to know the private part, if it should sign the web pages it serves with this certificate.
The conversion into a so-called pkcs file goes like this:
joerg@store:~/ca$ openssl pkcs12 -export -out drucker.pfx -inkey joergsCA/private/drucker.pem -in joergsCA/certs/drucker_cert.pem
this drucker.pfx file is then uploaded through the web interface of the printer. With that, I don’t get the ugly https warnings any longer. But careful, the printer serves as the default over http (not over https).
Another story is, how to import the ca certificate on your mobile phone, Android in my case.