Vytvoření vlastní certifikační autority a tvorba vlastních self-signed certifikátů

Publikováno: 3.11.2017

V tomto krátkém článku si ukážeme, jak si vygenerovat vlastní certifikační autoritu, a s její pomocí podepisovat vlastní self-signed certifikáty, které budou mít vyplněné subjectAltName (Subject Alternative Name), a díky tomu budou v pořádku fungovat v Chromu 58 a vyšším.

Celý článek

Text vyšel původně na blogu autora.

Návod se vám bude hodit hlavně pro vývoj, kdy si chceme lokálně zprovoznit https připojení a potřebujeme, aby se tvářilo jako důvěryhodné. Ale případně si takto můžeme generovat certifikáty třeba i pro intranetové domény a v nejhorším případě i pro veřejné domény.

Proč vytvářet vlastní certifikační autoritu a nikoliv pouze vlastní self-signed certifikáty?

Hlavní výhoda je, že do systému/prohlížeče (třeba Firefox má vlastní úložiště certifikátů) stačí naimportovat certifikát certifikační autority a pak všechny podepsané certifikáty touto autoritou budou automaticky důvěryhodné.

Nejprve si vygenerujeme certifikační autoritu. Zde jsou dvě možnosti, podle toho, zda chceme mít soukromý klíč chráněný heslem. Jde o zjednodušený návod z datacenteroverlords.com. Pokud nechceme mít soukromí klíč chráněný heslem, použijeme příkaz:

sudo openssl genrsa -out /etc/ssl/private/rootCA-Development.key 2048

A pokud chceme, přidáme přepínač -des3 takto:

sudo openssl genrsa -des3 -out /etc/ssl/private/rootCA-Development.key 2048

Následující postup je už stejný:

sudo chmod 600 /etc/ssl/private/rootCA-Development.key 2048
sudo openssl req -x509 -new -nodes -key /etc/ssl/private/rootCA-Development.key -sha256 -days 3650 -subj "/C=CZ/ST=Prague/L=Prague/O=Development" -out /etc/ssl/certs/rootCA-Development.pem

Samořejmě si můžete upravit parametry v -subj. Jejich význam je C=country, ST=state, L=locality a O=organization. Soubor /etc/ssl/certs/rootCA-Development.pem si pak naimportujeme jako důvěryhodný do systému nebo prohlížeče (vygooglete si, jak to udělat ve svém systému/prohlížeči).

Zbývá nám vytvořit skript, který bude generovat žádané certifikáty pro naše domény. Do jednoho certifikátu může zadat jednu a více domén. Vždy se generuje wildcard certifikát, takže bude platný i pro všechny subdomény. Z toho důvodu domény zadáváme bez www. Vytvoříme tedy skript s název generate-certificate:

sudo nano /usr/local/bin/generate-certificate

S obsahem:

#!/bin/bash
 
###
# How to generate certificate authority:
#  -> without password:
#    sudo openssl genrsa -out /etc/ssl/private/rootCA-Development.key 2048
#  -> with password:
#    sudo openssl genrsa -des3 -out /etc/ssl/private/rootCA-Development.key 2048
#
#    sudo chmod 600 /etc/ssl/private/rootCA-Development.key 2048
#    sudo openssl req -x509 -new -nodes -key /etc/ssl/private/rootCA-Development.key -sha256 -days 3650 -subj "/C=CZ/ST=Prague/L=Prague/O=Development" -out /etc/ssl/certs/rootCA-Development.pem
###
 
if [ "$EUID" -ne 0 ]; then
  echo "Please run as root"
  exit 1
fi
 
if [ $# -eq 0 ]; then
  echo "Please specify domain(s)."
  echo "Usage: $0 <main domain> [another domain] [another domain] ..."
  exit 2
fi
 
ROOTCA="Development"
 
# -> for certificate authority with password uncomment the line below:
#read -p "Enter rootCA-${ROOTCA}.key password: " PASSWORD
 
DOMAIN=$1
CONF="/tmp/$DOMAIN.openssl.cnf"
PRIVATE_KEY="/etc/ssl/private/$DOMAIN.key"
CERTIFICATE_REQUEST="/etc/ssl/certs/$DOMAIN.crt.req"
CERTIFICATE="/etc/ssl/certs/$DOMAIN.crt"
ANOTHER_DOMAINS=""
ANOTHER_DOMAINS_INFO=""
 
ANOTHER_DOMAIN_INDEX=3
for ANOTHER_DOMAIN in ${@:2}
do
  ANOTHER_DOMAINS="${ANOTHER_DOMAINS}DNS.${ANOTHER_DOMAIN_INDEX} = ${ANOTHER_DOMAIN}"$'\n'
  ANOTHER_DOMAIN_INDEX=$((ANOTHER_DOMAIN_INDEX + 1))
  ANOTHER_DOMAINS="${ANOTHER_DOMAINS}DNS.${ANOTHER_DOMAIN_INDEX} = *.${ANOTHER_DOMAIN}"$'\n'
  ANOTHER_DOMAIN_INDEX=$((ANOTHER_DOMAIN_INDEX + 1))
 
  ANOTHER_DOMAINS_INFO="-> ${ANOTHER_DOMAIN}"$'\n'
done
 
cat > $CONF <<-EOF
[req]
default_bits = 2048
prompt = no
x509_extensions = v3_req
distinguished_name = dn
 
[dn]
C = CZ
ST = Prague
L = Prague
O = $ROOTCA
CN = *.$DOMAIN
 
[v3_req]
subjectAltName = @alt_names
 
[alt_names]
DNS.1 = $DOMAIN
DNS.2 = *.$DOMAIN
$ANOTHER_DOMAINS
EOF
 
openssl genrsa -out $PRIVATE_KEY 2048
chmod 600 $PRIVATE_KEY
openssl req -new -config $CONF -key $PRIVATE_KEY -out $CERTIFICATE_REQUEST
 
openssl x509 -req -in $CERTIFICATE_REQUEST -CA /etc/ssl/certs/rootCA-${ROOTCA}.pem -CAkey /etc/ssl/private/rootCA-${ROOTCA}.key \
  -CAcreateserial -out $CERTIFICATE -days 3650 -sha256 -extfile $CONF -extensions 'v3_req'
# -> for certificate authority with password uncomment the line below and remove this line and the one up
#  -CAcreateserial -out $CERTIFICATE -days 3650 -sha256 -extfile $CONF -extensions 'v3_req' -passin pass:$PASSWORD
 
rm $CERTIFICATE_REQUEST
rm $CONF
 
chmod 600 $PRIVATE_KEY
 
echo "Self signed certificate ${CERTIFICATE} and private key ${PRIVATE_KEY} for main domain ${DOMAIN} were generated with 10 years expiration time"
 
if [ -z "$ANOTHER_DOMAINS_INFO" ]; then
  echo "Another domains:"
  echo ${ANOTHER_DOMAINS_INFO}
fi

A nastavíme skript jako spustitelný:

sudo chmod a+x /usr/local/bin/generate-certificate

Pokud jsme vygenerovali soukromý klíč pro certifikační autoritu chráněný heslem, odkomentujeme řádek začínající #read -p ... a u příkazu openssl x509 ... odkomentujeme třetí řádek a druhý vymažeme. Skript se nás pak před generováním vždy zeptá na heslo. Můžeme ještě upravit informace o certifikátu v sekci [dn] stejně jako jsme upravili informace o certifikační autoritě.

Certifikát, pro domény domain1.com a domain2.org pak vygenerujeme takto:

sudo generate-certificate domain1.com domain2.org

Vygenerovaný certifikát najdeme v souborech /etc/ssl/private/domain1.com.key (privátní klíč) a /etc/ssl/private/domain1.com.crt (certifikát). Tyto soubory pak už jen použijeme v nastavení nginx, Apache, případně jiného softwaru. A bude platit pro domény domain1.com*.domain1.comdomain2.org a *.domain2.org.

Podotýkám, že nejsem bezpečnostní ani linuxový expert. Pouze jsem zkompletoval několik návodů do funkčního celku. Je tedy možné, že něco by šlo řešit elegantněji, případně nepoužívám správnou terminologii. Nebojte se mě opravit v komentářích. Tento návod je funkční minimálně na Debianu Jessie a Stretch, ale je dost pravděpodobné, že poběží na více systémech.

Nahoru
Tento web používá k poskytování služeb a analýze návštěvnosti soubory cookie. Používáním tohoto webu s tímto souhlasíte. Další informace