x509 certificat managment
What are x509 certificates ?
According to Wikipedia, x509 is a standard defining the format of public key certificates. They are used in many Internet protocols, including TLS/SSL, which is the basis for HTTPS (the secure protocol for browsing the web).
Purpose
The purpose of having my own Certification Authority (CA) allow me to generate self signed certificates for non public uses. Hosted services on my own private network prevent me from getting free certificates from well known Let's Encrypt authority.
Since I host more than one service and I want that all my devices (laptop, phone, ...) can have access to them without having to install certificate every 3 weeks (when I'm updating hostnames for exemple). I have decided to create my own CA and generate signed certificates validated by it. That way, I only have to install the root CA on all my device to make it work.
Making my own certification authority
All I need is a linux environment and openssl
.
Generating the secret
First let's generate the private key with the following command :
Ouput :
Generating RSA private key, 4096 bit long modulus
.................................................................++
......................................................................................................................................................................++
e is 65537 (0x10001)
I now have a nice looking private key :
-----BEGIN RSA PRIVATE KEY-----
MIIJKAIBAAKCAgEA2IxiR6U/B6Ypd1/3KG5Pxk/BY47HzHpBAHnEFsMHdcpCNNXO
GxqhUsIHBGMc0I2xa0WiyNJB4k5qGwL58J1TK/kKaW8yOOGajawvhjL/6bYXgN1I
[...]
rcL3YJyl/m0mlYl80syPPViHM9TD7uwQi/M9DPeOGLwVuCYzpl3qAkQRaTwQc2Ev
5hffBNz+evhf2Q7iUCmWQFizIFlFpOCq1f/jvpleqf8ChG6EhNRgvAFIUMc=
-----END RSA PRIVATE KEY-----
This file should be kept secret and securelly stored offline.
Generating the certificate configuration
Now that I have the secret part, I need to generate the public part : the x509 certificate. Using the default OpenSSL configuration:
[ req ]
default_bits = 4096
default_keyfile = root-CA.key
encrypt_key = no
utf8 = yes
distinguished_name = req_distinguished_name
prompt = no
x509_extensions = v3_ca
[ req_distinguished_name ]
countryName = FR
stateOrProvinceName = France
localityName = Paris
organizationName = Example
commonName = example.org
[ v3_ca ]
subjectKeyIdentifier = hash
basicConstraints = critical,CA:true,pathlen:1
keyUsage = critical,keyCertSign
This configuration should be kept for the next time I need to regenerate the root certificate. Keep in mind that this cert shouldn't be changed too often otherwise it make the main purpose useless.
You can adjust this configuration based on your need.
Generating the root certificate
Using the previous configuration, I have generated the self signed root CA :
openssl req -x509 -new -nodes \
-config root-CA-openssl.cnf \
-key root-CA.key \
-sha256 -days 1024 \
-out root-CA.crt
Checking the content of the certificate :
Output :
Certificate:
Data:
Version: 1 (0x0)
Serial Number: 11676879669831540892 (0xa20c9c31654a209c)
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=FR, ST=France, L=Paris, O=Example, CN=example.org
Validity
Not Before: Feb 6 15:53:58 2022 GMT
Not After : Nov 26 15:53:58 2024 GMT
Subject: C=FR, ST=France, L=Paris, O=Example, CN=example.org
[...]
X509v3 extensions:
X509v3 Subject Key Identifier:
F1:FA:C4:50:A4:7F:53:D3:6C:D5:EF:48:72:24:B8:CE:08:10:3F:94
X509v3 Basic Constraints: critical
CA:TRUE, pathlen:1
X509v3 Key Usage: critical
Certificate Sign
[...]
This command generate the certificate file and sign its content with the private key.
I now have a Authority Certificate, I can generate all my apps certificates and sign them with it.
Verifying that the certificate and the private key match
Get the checkum of the certificat modulus :
Do the same for the private key :
You should get exactly the same output with both commands :
Creating certificates for my apps
Generating the secret
Same as for the root CA, I need to generate a secret key.
I can use an identical command as earlier :
Generating the openssl config
I now need to create the OpenSSL configuration for my certificate using the default OpenSSL configuration :
[ req ]
default_bits = 2048
default_keyfile = my-app.key
encrypt_key = no
utf8 = yes
distinguished_name = req_distinguished_name
req_extensions = v3_req
prompt = no
[ req_distinguished_name ]
countryName = FR
stateOrProvinceName = France
localityName = Paris
organizationName = Example
commonName = my-app.example.org
[v3_req]
subjectKeyIdentifier = hash
subjectAltName = @alt_names
[ alt_names ]
DNS.1 = my-app.example.org
DNS.2 = extra.my-app.example.org
Note here that the subjectAltName
parameter and the alt_names
are very important. Now every browser or phone application require that the hostname exposed by the web application should be specified in this section.
You can still add more than one alternative name to the certificate. This allow you to use the same certificate for multiple application. Make sure to use different certificate based on the security level you need for your apps.
Generating the certificate request
In order to generate a certificate that is signed by my root CA, I need to generate a certificate request. Using the following command, I can generate the request and sign it with the app private key :
I can review the content of my request with :
Output :
Certificate Request:
Data:
Version: 0 (0x0)
Subject: C=FR, ST=France, L=Paris, O=Example, CN=my-app.example.org
[...]
Signing my app certificate with the root CA
Lastly I need to use my root CA to generate my application certificate based on the request and ensure its authenticity.
I only need to use the following command :
openssl x509 -req \
-CA root-CA.crt \
-CAkey root-CA.key \
-CAcreateserial \
-in my-app.csr \
-days 500 -sha256 \
-out my-app.crt
To verify the content of the newly generated certificate, I can run the following conmmand :
Output :
Certificate:
Data:
Version: 1 (0x0)
Serial Number: 15807445207358136962 (0xdb5f53aa27086282)
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=FR, ST=France, L=Paris, O=Example, CN=example.org
Validity
Not Before: Feb 6 16:22:38 2022 GMT
Not After : Jun 21 16:22:38 2023 GMT
Subject: C=FR, ST=France, L=Paris, O=Example, CN=my-app.example.org
Verifiying the full trust chain
Now that I have the certificate for my application, I need to make sure that the root CA validate the authenticity of it.
Using one last openssl
command :
Ouput :
Also with an intermediate certificate :