After spending so much time this week dealing with repercussions relating to the OpenSSL “Heartbleed” bug, I thought it was time to go back and properly set myself up as a CA, like I had been meaning to. Why would anybody want to do this? Well, there are a couple of good reasons.
Just like a self-signed certificate, a user will still get a security warning if he visits a site that uses a certificate that is signed by a CA that the browser doesn’t recognize, but it’s trivially easy to import the generated CA into the browser as a trusted CA. Once the certificate is imported, the browser will trust the SSL’ed site just like it does that expensive Verisign cert. This is mainly convenient for personal use, for example when securely accessing data and/or services remotely from a home network.
Another use case is securing traffic on an internal network where many services are exposed, possibly in an app that uses a service oriented architecture. Since these are not public-facing, you simply generate a key and cert for each service, and then import the CA certificate into each client application. Now your network traffic is encrypted and you’re in control of the chain of trust. You can even use the optional “Organizational Unit (OU)” field on the certificate to pass meta-data between applications in your SOA. Docker allows you to authenticate clients in a similar fashion, which is described here.
Here’s how you’d actually go about doing this. First, be sure you have a version of openssl that has been patched for Heartbleed:
$ openssl version -a OpenSSL 1.0.1e 11 Feb 2013 built on: Mon Apr 7 20:33:19 UTC 2014 platform: debian-amd64 options: bn(64,64) rc4(16x,int) des(idx,cisc,16,int) blowfish(idx) compiler: cc -fPIC -DOPENSSL_PIC -DZLIB -DOPENSSL_THREADS -D_REENTRANT -DDSO_DLFCN -DHAVE_DLFCN_H -m64 -DL_ENDIAN -DTERMIO -g -O2 -fstack-protector --param=ssp-buffer-size=4 -Wformat -Werror=format-security -D_FORTIFY_SOURCE=2 -Wl,-Bsymbolic-functions -Wl,-z,relro -Wa,--noexecstack -Wall -DOPENSSL_NO_TLS1_2_CLIENT -DOPENSSL_MAX_TLS1_2_CIPHER_LENGTH=50 -DMD32_REG_T=int -DOPENSSL_IA32_SSE2 -DOPENSSL_BN_ASM_MONT -DOPENSSL_BN_ASM_MONT5 -DOPENSSL_BN_ASM_GF2m -DSHA1_ASM -DSHA256_ASM -DSHA512_ASM -DMD5_ASM -DAES_ASM -DVPAES_ASM -DBSAES_ASM -DWHIRLPOOL_ASM -DGHASH_ASM OPENSSLDIR: "/usr/lib/ssl"
If it was built on April 7 or later, then you have a patched version. Now, generate the private key for your new CA. Be sure to include “-des3” so your key is password-protected.
$ openssl genrsa -des3 -out tongenRootCA.key 4096
Be sure to keep this key secure. Now self-sign your own root CA key. This is apparently how all the big CA’s do it.
$ openssl req -x509 -new -nodes -key tongenRootCA.key -days 1024 -out tongenRootCA.pem Enter pass phrase for tongenRootCA.key: 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]:Minnesota Locality Name (eg, city) :Minneapolis Organization Name (eg, company) [Internet Widgits Pty Ltd]:Tongen Technologies Organizational Unit Name (eg, section) : Common Name (e.g. server FQDN or YOUR name) :Tongen Internet Authority Email Address :
Ok, now you’re a CA! Congratulations! If you can somehow manage to get your cert to be shipped with any big-name browsers or other software, you could make some serious money. But being a CA is pretty pointless unless you sign some SSL keys, so let’s create one that we can sign. This part should be pretty familiar if you’ve ever purchased an SSL certificate before.
$ openssl genrsa -out andrewtongen.net.key 2048
Now generate the corresponding CSR:
$ openssl req -new -key andrewtongen.net.key -out andrewtongen.net.csr 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]:Minnesota Locality Name (eg, city) :Minneapolis Organization Name (eg, company) [Internet Widgits Pty Ltd]:Tongen Technologies Organizational Unit Name (eg, section) : Common Name (e.g. server FQDN or YOUR name) :*.andrewtongen.net Email Address : Please enter the following 'extra' attributes to be sent with your certificate request A challenge password : An optional company name :
Now for the fun part. We’ll sign the SSL key we just generated with the CA certificate and key we generated earlier:
$ openssl x509 -req -in andrewtongen.net.csr -CA path/to/tongenRootCA.pem -CAkey path/to/tongenRootCA.key -CAcreateserial -out andrewtongen.net.crt -days 1024 Signature ok subject=/C=US/ST=Minnesota/L=Minneapolis/O=Tongen Technologies/CN=*.andrewtongen.net Getting CA Private Key Enter pass phrase for path/to/tongenRootCA.key:
And you’re done! You can now install the SSL cert and key on your webserver for encrypted traffic.
Oh, by the way, here’s the certificate for the CA I just created.