There are many reasons why you may need to create your own CA. Although you are advised to sign internet facing services with a certificate from a trusted root entity you have much more freedom when it comes to your intranet or vpn infrastructure. The other use cases may include a WPA2 enterprise access point or an https connection to a private wiki page.
This ariticle describes ubuntu 12.10 and OpenSSL 1.0.1c
To generate a self-signed certificate using OpenSSL on Ubuntu is fairly easy, even though cryptography behind it is not. You can use this post a step by step tutorial. Firstly we will create a CA, then we will use it to sign certificate requests which will be turned into self-signed SSL certificates.
Please note that this is not an introduction to public-key cryptography.
Set up
OpenSSL should be installed by default on ubuntu. You may want to verify that with:
$ which openssl /usr/bin/openssl
In case it's not (and your output is empty) type:
$ sudo apt-get install openssl
Directories
OpenSSL requires a certain directory structure. I will assume here that
the root directory is named my-ca
. We can create the structure as
follows:
$ mkdir -p my-ca/{certs,crl,newcerts,private}
Files
Additionally we want to create a certificate database: index.txt
, a file
that stores a serial number to be generated for a certificate: serial
and a configuration file openssl.cnf
. In case of the latter we will
simply copy the default one (/etc/ssl/openssl.cnf
in Ubuntu).
$ cd my-ca (my-ca)$ cp /etc/ssl/openssl.cnf . (my-ca)$ touch index.txt (my-ca)$ echo '01' > serial
When we are done we should see the following:
. ├── certs/ ├── crl/ ├── newcerts/ ├── private/ ├── index.txt ├── openssl.cnf └── serial
Config file
Now we need to customize the configuration file to match the my-ca
directory structure. Edit openssl.cnf
with your favourite editor.
[ CA_default ] dir = . # <-- Change this certs = $dir/certs crl_dir = $dir/crl database = $dir/index.txt #unique_subject = no new_certs_dir = $dir/newcerts certificate = $dir/certs/my-ca.crt # <-- Change this serial = $dir/serial crlnumber = $dir/crlnumber crl = $dir/crl.pem private_key = $dir/private/my-ca.key # <-- Change this RANDFILE = $dir/private/.rand
Diff should look like this:
(my-ca)$ diff /etc/ssl/openssl.cnf openssl.cnf 42c42 < dir = ./demoCA # Where everything is kept --- > dir = . # Where everything is kept 50c50 < certificate = $dir/cacert.pem # The CA certificate --- > certificate = $dir/certs/my-ca.pem # The CA certificate 55c55 < private_key = $dir/private/cakey.pem# The private key --- > private_key = $dir/private/my-ca.key # The private key
Extensions
For a reference, we encounter following extensions on the key files.
File extension | Meaning |
---|---|
KEY | A private key, should not be distributed to public. |
CSR | A certificate request - this is generated by us or anyone who whats us to sign his or her certificate. After a certificate is generated this can be deleted. |
CRT | A certificate, which can be publicly distributed. |
CRL | A certificate revocation list, which can and should be publicly distributed. |
PEM | Some servers need a single file containing concatenated KEY and CRT. PEM files can be used for that purpose. |
Keys
Since we have the infrastructure in place we can start generating the keys.
CA key
Firstly, we need to generate the CA key. You will need to provide a pass-phrase and the details of your organization.
(my-ca)$ openssl req -config openssl.cnf -new -x509 -extensions v3_ca -keyout private/my-ca.key -out certs/my-ca.crt -days 1825
Generating a 2048 bit RSA private key ....................+++ ...........................................................................+++ writing new private key to 'private/my-ca.key' 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) [AU]:PL State or Province Name (full name) [Some-State]:Wielkopolska Locality Name (eg, city) []:Poznan Organization Name (eg, company) [Internet Widgits Pty Ltd]:AcmeLTD Organizational Unit Name (eg, section) []:InternetOps Common Name (e.g. server FQDN or YOUR name) []:acme.pl Email Address []:cert@acme.pl
req
- PKCS#10 X.509 Certificate Signing Request (CSR) Management
-config openssl.cnf
- Use customized OpenSSL config
-new
- Generate new certificate request and prompt the user for field
values (like
Country Name
, etc). -x509
- Output self-signed certificate instead of a certificate request.
-extensions v3_ca
- This is a CA certificate.
-keyout private/my-ca.key -out certs/my-ca.crt
- Where the certificate and its key should be generated.
-days 1825
- The certificate is valid roughly five years.
Please note that by default the organization details are interpreted as
ASCII strings. You may want to use -utf8
to change it.
We have our own CA now! We are ready to sign any incoming certificate requests.
Import the root CA certificate on your intranet machines.
If you do not want to see these warnings that connection is untasted and you should be take out from there, import the CA certificate to a browser/operating system key store. You can follow the steps outlined here:
You should import the my-ca.crt
file for this purpose.
Server certificate request
We will start with a private key for the webserver.
(my-ca)$ openssl genrsa -out private/my-domain.key 2048
It is generated without a password, so if you restart a webserver the certificate needs not to be decrypted by entering a password.
Now we can start with the request.
(my-ca)$ openssl req -new -key private/my-domain.key -out my-domain.csr
You will be prompted for the organization details, so consider using also
the -utf8
option. Please bear in mind that the Common Name
field is
very important, as it indicates your domain, e.g. my-domain.com
. You may
also want to use *.my-domain.com
for certificates valid also for
subdomains.
Finally, we can sign it.
(my-ca)$ openssl ca -config openssl.cnf -policy policy_anything -out certs/my-domain.crt -infiles my-domain.csr
policy_anything
is defined in the openssl.cnf
.
This creates two files:
- certs/my-domain.crt
- Signed certificate
- newcerts/01.pem
- The same with certificate serial id (not needed).
The key (my-domain.key
) and the certificate (my-domain.crt
) can be used
to configure https connection to a web server. The certificate request
(my-domain.csr
) can be safely deleted.
Verify the certificate
You can see the certificate’s info with the following:
(my-ca)$ openssl x509 -subject -issuer -enddate -noout -in certs/my-domain.crt
Or the following:
(my-ca)$ openssl x509 -in certs/my-domain.crt -noout -text
And verify that the certificate is valid for server authentication with the following:
(my-ca)$ openssl verify -purpose sslserver -CAfile certs/myca.crt certs/my-domain.crt
Sources
Hope this post is useful for you. I used the following sources when preparing it:
- http://www.area536.com/projects/be-your-own-certificate-authority-with-openssl/
- http://www.g-loaded.eu/2005/11/10/be-your-own-ca/
- And following man pages:
openssl
,req
,ca
,x509
,x509v3_config
.