pekand - blog
world to explore

Create own self signed certificate - tutorial

This tutorial learn you how create self signed certificate for develoment. In first part is certificate authority created. After import CA certificate to your system your page in browser or other applications don't show certificate error and appear as valid webpage. Next part show how create self signed certificate and use it in apache or nginx server.

Create self signed authotiry with openssl command.

Create private key with 2048 bits size for self signed certification authority [man pages]. Certificate authority private key must by protected with password. DES3 is used for encrypt of the private key. Whenever is the private key used, user will be prompted for the password.

openssl genrsa -des3 -out myCA.key 2048

DES is symmetric algorithm for the encryption.
DES3 is symmetric algorithm for the encryption which applies the DES cipher algorithm three time for each block for better security.

Generate certificate in PEM format [man pages]:

openssl req -x509 -new -nodes -key myCA.key -sha256 -days 1825 -out myCA.pem -subj "/C=SK/ST=Slovakia/L=Bratislava/O=organization/OU=organization unit/CN=myCA"

-x509 standard defining the format of public key certificates X.509
-nodes skip private key encription (no des).
-days validity of certificate in days (5 * 365=1825)
-sha256 digest algorithm for signature.

Convert certificate from ascii based PEM format to binnary DER format [man pages]

openssl x509 -outform der -in myCA.pem -out myCA.crt

-outform der Distinguished Encoding Rules - A binary format [X.509]

Create self signed certificate for page.

Create private key for your certificate.

openssl genrsa -out myPage.key 2048

Create certificate request. Certificate request is used when requester and authority is not some person. Requester provide csr request to authority and authority create certificate from request. This allow to requester's private key be hidden.

openssl req -new -key myPage.key -out myPage.csr -subj "/C=SK/ST=Slovakia/L=Bratislava/O=Organization/OU=Organization Unit/CN=myPage"

Create configuration ext file myPage.ext. In this file you can customize your alt_names. You can use asterisk for subdomain but not for top domain (*.dev not work) because browser block page. If you use wildcard for subdomain you don't need explicitly list domains like is in example because *.mypage.dev cover example.mypage.dev, admin.mypage.dev and db.mypage.dev, but you can.

authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names

[alt_names]

DNS.1 =  mypage.dev
DNS.2 =  *.mypage.dev
DNS.3 =  example.mypage.dev
DNS.4 =  admin.mypage.dev
DNS.5 =  db.mypage.dev

Create certificate from certificate request and subscribe certificate with myCA authority.

openssl x509 -req -in myPage.csr -CA myCA.pem -CAkey myCA.key -CAcreateserial -out myPage.crt -days 1825 -sha256 -extfile myPage.ext

All commands together

All previous commands in one script. Don't forget create myPage.ext file. You don't need create myCA certificate evry time. After overwrite myCA files you must import certificate to os. For this reason after myPage.ext update run only last command for create certificate signed by myCA authority.

#!/bin/bash
set -o xtrace

openssl genrsa -des3 -out myCA.key 2048
openssl req -x509 -new -nodes -key myCA.key -sha256 -days 1825 -out myCA.pem -subj "/C=SK/ST=Slovakia/L=Bratislava/O=organization/OU=organization unit/CN=myCA"
openssl x509 -outform der -in myCA.pem -out myCA.crt

openssl genrsa -out myPage.key 2048
openssl req -new -key myPage.key -out myPage.csr -subj "/C=SK/ST=Slovakia/L=Bratislava/O=Organization/OU=Organization Unit/CN=myPage"
openssl x509 -req -in myPage.csr -CA myCA.pem -CAkey myCA.key -CAcreateserial -out myPage.crt -days 1825 -sha256 -extfile myPage.ext

read -p "done"

Example output in command line:

+ openssl genrsa -des3 -out myCA.key 2048
Generating RSA private key, 2048 bit long modulus
..........+++
.......+++
e is 65537 (0x10001)
Enter pass phrase for myCA.key:
Verifying - Enter pass phrase for myCA.key:
+ openssl req -x509 -new -nodes -key myCA.key -sha256 -days 1825 -out myCA.pem -subj '/C=SK/ST=Slovakia/L=Bratislava/O=organization/OU=organization unit/CN=myCA'
Enter pass phrase for myCA.key:
+ openssl x509 -outform der -in myCA.pem -out myCA.crt
+ openssl genrsa -out myPage.key 2048
Generating RSA private key, 2048 bit long modulus
..................................................................+++
............+++
e is 65537 (0x10001)
+ openssl req -new -key myPage.key -out myPage.csr -subj '/C=SK/ST=Slovakia/L=Bratislava/O=Organization/OU=Organization Unit/CN=myPage'
+ openssl x509 -req -in myPage.csr -CA myCA.pem -CAkey myCA.key -CAcreateserial -out myPage.crt -days 1825 -sha256 -extfile myPage.ext
Signature ok
subject=/C=SK/ST=Slovakia/L=Bratislava/O=Organization/OU=Organization Unit/CN=myPage
Getting CA Private Key
Enter pass phrase for myCA.key:
+ read -p done
done

Import certificate authority to system

Import certificate in Windows 10

You can check detail of certificate with double click on myCA.crt

For certificate authority import open certificate manager certmgr.msc as administrator and import myCA.crt to "Trusted Root Certification Authorities" with mouse right click and select "All tasks/Import..."

Import certificate in Ubuntu 20

You must copy certificate in PEM format. Command dpkg-reconfigure is GUI application. You must pick up your certificate from options. Check command line output if your certificate was imported.

sudo mkdir /usr/share/ca-certificates/extra
sudo cp myCA.pem /usr/share/ca-certificates/extra/myCA.crt
sudo dpkg-reconfigure ca-certificates

You can use curl to validate your certificate (after web server configuration).

curl https://mypage.dev

Use certificate in http server

apache example configuration

Example use of vhost apache module. After new folder is created apache use folder automaticaly without server restart, but you must manualy update system hosts file. If you use wildcard for subdomain in your myPage.ext file you don't need update certificate. Wilcard for top domain like *.dev don't work and browser block page.

LoadModule vhost_alias_module modules/mod_vhost_alias.so
LoadModule http2_module modules/mod_http2.so

Protocols h2 h2c http/1.1

<VirtualHost *:80>
  RewriteEngine On
  RewriteCond %{HTTPS} off
  RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI}
</VirtualHost>

<VirtualHost *:443>
  SSLEngine on
  
  SSLCertificateFile "/cert/myPage.crt"
  SSLCertificateKeyFile "/cert/myPage.key"

  ServerName vhosts.fqdn
  ServerAlias *.dev

  VirtualDocumentRoot "/Web/%0/public"

  ErrorLog logs/error_hosts.log
  CustomLog logs/access_hosts.log combined

  <Directory "/Web/">
    Options Indexes FollowSymlinks MultiViews
    AllowOverride All
    Require all granted
  </Directory>
</VirtualHost>

Now you can access to page example.mypage.dev trough folder /Web/example.mypage.dev/public/index.html

nginx example configuration

You can use nginx proxy to create https access to other applications listening on other custom port and not secured.

server {
    listen 80 default_server;
    listen [::]:80 default_server;
    server_name _;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    server_name _;

    ssl_certificate           /cert/myPage.crt;
    ssl_certificate_key       /cert/myPage.key;
    
    ssl on;
    ssl_session_cache  builtin:1000  shared:SSL:10m;
    ssl_protocols  TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers HIGH:!aNULL:!eNULL:!EXPORT:!CAMELLIA:!DES:!MD5:!PSK:!RC4;
    ssl_prefer_server_ciphers on;

    location / {
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header Host $http_host;
        proxy_intercept_errors on;

        proxy_pass http://webserver:80;
        proxy_read_timeout  90;
    }   
}
Comments: