Comandos para crear una autoridad de certificación (CA) con OpenSSL

Escrito por picodotdev el .
gnu-linux planeta-codigo
Enlace permanente Comentarios

Los certificados autofirmados no son suficientes para un entorno de producción. En producción hay que usar certificados firmados por una entidad de confianza. AWS Certificate Manager ofrece la suya pero tiene un coste elevado y los certificados de otras entidades tampoco son baratos. Para certificados de uso interno en una organización que proporcionan comunicaciones seguras OpenSSL permite con una serie de comandos crear una autoridad de certificación o CA en la que los servidores y clientes internos confíen. Las funciones de la CA incluyen crear certificados a partir de las solicitudes de los certificados para los servidores y también la revocación y renovación de certificados.

Para usar el protocolo seguro HTTPS en un servidor web es necesario al menos generar un certificado autofirmado que incluya el dominio del sitio web. El certificado autofirmado proporciona comunicaciones seguras entre el servidor y cliente pero los clientes no lo consideran de confianza de modo que han de omitir la validación del certificado, un entorno de desarrollo o pruebas es suficiente pero en un escenario de producción para añadir más seguridad donde hay varios servidores que además requieren y validan también el certificado del cliente es necesario utilizar certificados generados por una entidad en la que se confíe, esta es la autoridad de certificación. La autoridad de certificación o CA es una entidad en la que se confía, si una CA ha firmado digitalmente un certificado esta asegura que el certificado pertenece a quien dice pertenecer. Las funciones de una CA son firmar los certificados que se le envían, de revocar los certificados cuando han sido comprometidos o de renovarlos cuando su validez expira.

AWS en su oferta de productos tiene AWS Certificate Manager que hace las funciones de autoridad de certificados, delega la complejidad de hacer las funciones de autoridad de certificados pero su inconveniente es que tiene el significativo precio de $400 mensuales más un pequeño coste por certificado emitido. La herramienta OpenSSL permite hacer las funciones de una autoridad de certificación con un conjunto de comandos.

Crear la clave y certificado de la autoridad de certificación raíz

El certificado de una autoridad de certificación es un certificado autofirmado que se utilizar para comprobar que la firma de los certificados que emite la entidad es válida. Es necesario crear un par de claves asimétricas privada y pública y posteriormente generar su certificado.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
#!/usr/bin/env bash
set -e

CA_PATH=ca

export CA_DIR=.
export INTERMEDIATE_DIR=./intermediate

mkdir -p $CA_PATH/certs $CA_PATH/crl $CA_PATH/newcerts $CA_PATH/private $CA_PATH/intermediate/
cp openssl/ca/openssl*.conf $CA_PATH/
cp openssl/intermediate/openssl*.conf $CA_PATH/intermediate/
cd $CA_PATH

chmod 700 private
touch index.txt
echo 1000 > serial

# CA

openssl genrsa -out private/ca.key.pem 8192
chmod 400 private/ca.key.pem
ca-root-1.sh

El certificado de la CA raíz es simplemente un certificado autofirmado.

1
2
3
4
5
$ openssl req -config openssl.conf \
      -key private/ca.key.pem \
      -new -x509 -days 7300 -sha256 -extensions v3_ca \
      -subj "/C=ES/ST=Spain/L=Madrid/O=Acme S.A./CN=Acme S.A (CA)" \
      -out certs/ca.cert.pem
ca-root-2.sh

Archivos y directorios de la autoridad de certificación con OpenSSL

Al crear el certificado se utiliza un archivo de configuración donde se guardan las opciones por defecto de configuración que determinan varios aspectos de OpenSSL como directorios, políticas, fecha de validez de los certificados emitidos, campos de los certificados que emite o perfiles de firma entre algunos otros.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# OpenSSL root CA configuration file.
# Copy to `/root/ca/openssl.cnf`.

[ ca ]
# `man ca`
default_ca = CA_default

[ CA_default ]
# Directory and file locations.
dir               = $ENV::CA_DIR
certs             = $dir/certs
crl_dir           = $dir/crl
new_certs_dir     = $dir/newcerts
database          = $dir/index.txt
serial            = $dir/serial
RANDFILE          = $dir/private/.rand
copy_extensions   = none

# The root key and root certificate.
private_key       = $dir/private/ca.key.pem
certificate       = $dir/certs/ca.cert.pem

# For certificate revocation lists.
crlnumber         = $dir/crlnumber
crl               = $dir/crl/ca.crl.pem
crl_extensions    = crl_ext
default_crl_days  = 30

# SHA-1 is deprecated, so use SHA-2 instead.
default_md        = sha256

name_opt          = ca_default
cert_opt          = ca_default
default_days      = 1825
preserve          = no
policy            = policy_strict

[ policy_strict ]
# The root CA should only sign intermediate certificates that match.
# See the POLICY FORMAT section of `man ca`.
countryName             = match
stateOrProvinceName     = match
organizationName        = match
organizationalUnitName  = optional
commonName              = supplied
emailAddress            = optional

[ policy_loose ]
# Allow the intermediate CA to sign a more diverse range of certificates.
# See the POLICY FORMAT section of the `ca` man page.
countryName             = optional
stateOrProvinceName     = optional
localityName            = optional
organizationName        = optional
organizationalUnitName  = optional
commonName              = supplied
emailAddress            = optional

[ req ]
# Options for the `req` tool (`man req`).
default_bits        = 8192
distinguished_name  = req_distinguished_name
string_mask         = utf8only

# SHA-1 is deprecated, so use SHA-2 instead.
default_md          = sha256

# Extension to add when the -x509 option is used.
x509_extensions     = v3_ca

[ req_distinguished_name ]
# See <https://en.wikipedia.org/wiki/Certificate_signing_request>.
countryName                     = Country Name (2 letter code)
stateOrProvinceName             = State or Province Name
localityName                    = Locality Name
0.organizationName              = Organization Name
organizationalUnitName          = Organizational Unit Name
commonName                      = Common Name
emailAddress                    = Email Address

# Optionally, specify some defaults.
countryName_default             = ES
stateOrProvinceName_default     = Spain
localityName_default            = Madrid
0.organizationName_default      =
organizationalUnitName_default  = Acme S.A. (CA)
emailAddress_default            =

[ v3_ca ]
# Extensions for a typical CA (`man x509v3_config`).
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true
keyUsage = critical, digitalSignature, cRLSign, keyCertSign

[ v3_intermediate_ca ]
# Extensions for a typical intermediate CA (`man x509v3_config`).
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true, pathlen:0
keyUsage = critical, digitalSignature, cRLSign, keyCertSign

[ usr_cert ]
# Extensions for client certificates (`man x509v3_config`).
basicConstraints = CA:FALSE
nsCertType = client, email
nsComment = "OpenSSL Generated Client Certificate"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = clientAuth, emailProtection

[ server_cert ]
# Extensions for server certificates (`man x509v3_config`).
basicConstraints = CA:FALSE
nsCertType = server
nsComment = "OpenSSL Generated Server Certificate"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer:always
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth

[ crl_ext ]
# Extension for CRLs (`man x509v3_config`).
authorityKeyIdentifier=keyid:always

[ ocsp ]
# Extension for OCSP signing certificates (`man ocsp`).
basicConstraints = CA:FALSE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
keyUsage = critical, digitalSignature
extendedKeyUsage = critical, OCSPSigning
ca/openssl.conf

Crear la clave y certificado de la autoridad de certificación intermedia

De la confianza en la CA raíz depende toda la seguridad de los certificados que emite, que su clave privada y pública o certificado sean comprometidos es posiblemente lo peor que le puede ocurrir a una CA. Para minimizar el riesgo se intenta hacer el menor uso posible de la clave privada y pública de la autoridad de certificación raíz, para esto se suele crear una autoridad de certificación intermedia que es la que realmente firma, revoca y renueva los certificados para el servidor, clientes o usuarios. Si la CA intermedia es comprometida aún siendo también un problema grave de seguridad al menos la CA raíz puede crear una nueva CA intermedia en la que se pueda confiar.

La CA intermedia tiene su propio par de claves asimétricas privada y pública, también tiene su certificado que en este caso está firmado por la CA raíz.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# Intermediate CA

mkdir -p intermediate/certs intermediate/crl intermediate/csr intermediate/newcerts intermediate/private
chmod 700 intermediate/private
touch intermediate/index.txt
echo 1000 > intermediate/serial
echo 1000 > intermediate/crlnumber

openssl genrsa -out intermediate/private/intermediate.key.pem 8192
chmod 400 intermediate/private/intermediate.key.pem
ca-intermediate-1.sh

La CA raíz firma únicamente el certificado de la CA intermedia. La CA intermedia generar la solicitud de firma de certificado, la CA raíz lo firma y se genera el certificado firmado.

1
2
3
4
$ openssl req -config intermediate/openssl.conf -new -sha256 \
      -key intermediate/private/intermediate.key.pem \
      -subj "/C=ES/ST=Spain/L=Madrid/O=Acme S.A./CN=Acme S.A. (Intermediate CA)" \
      -out intermediate/csr/intermediate.csr.pem
ca-intermediate-2.sh

La CA recibe la solicitud de firma del certificado de la CA intermedia y la firma. La CA intermedia recibe las solicitudes de firma de certificados para los servidores, clientes y usuarios y genera los certificados firmados.

1
2
3
4
$ openssl ca -config openssl.conf \
      -extensions v3_intermediate_ca -days 3650 -batch -notext -md sha256 \
      -in intermediate/csr/intermediate.csr.pem \
      -out intermediate/certs/intermediate.cert.pem
ca-intermediate-3.sh

Una vez generado el certificado de la CA intermedia se puede inspeccionar el certificado y validar que la firma sea correcta utilizando el certificado de la CA raíz.

1
2
3
4
$ openssl x509 -noout -text \
      -in intermediate/certs/intermediate.cert.pem
$ openssl verify -CAfile certs/ca.cert.pem \
      intermediate/certs/intermediate.cert.pem
ca-intermediate-4.sh

Para validar los certificados emitidos por la CA intermedia se genera una cadena de certificados que incluye los certificados de la CA raíz y la CA intermedia, la cadena de certificados es simplemente la unión del contenido de ambos certificados.

1
2
3
$ cat intermediate/certs/intermediate.cert.pem \
      certs/ca.cert.pem > intermediate/certs/ca-chain.cert.pem
$ chmod 444 intermediate/certs/ca-chain.cert.pem
ca-intermediate-5.sh

La CA intermedia también utiliza su propio archivo de configuración de OpenSSL. En él se incluye la opción copy_extensions que permite copiar algunos atributos de la solicitud al certificado que genera, esto sirve para incluir en el certificado los múltiples Subject Alternative Name o SAN enviados en la solicitud. Si se permite emitir certificados con el mismo Subject es necesario utilizar la opción de configuración unique_subject = no.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
# OpenSSL intermediate CA configuration file.
# Copy to `/root/ca/intermediate/openssl.cnf`.

[ ca ]
# `man ca`
default_ca = CA_default

[ CA_default ]
# Directory and file locations.
dir               = $ENV::INTERMEDIATE_DIR
certs             = $dir/certs
crl_dir           = $dir/crl
new_certs_dir     = $dir/newcerts
database          = $dir/index.txt
serial            = $dir/serial
RANDFILE          = $dir/private/.rand
copy_extensions   = copy

# The root key and root certificate.
private_key       = $dir/private/intermediate.key.pem
certificate       = $dir/certs/intermediate.cert.pem

# For certificate revocation lists.
crlnumber         = $dir/crlnumber
crl               = $dir/crl/intermediate.crl.pem
crl_extensions    = crl_ext
default_crl_days  = 30

# SHA-1 is deprecated, so use SHA-2 instead.
default_md        = sha256

name_opt          = ca_default
cert_opt          = ca_default
default_days      = 1825
preserve          = no
policy            = policy_loose

[ policy_strict ]
# The root CA should only sign intermediate certificates that match.
# See the POLICY FORMAT section of `man ca`.
countryName             = match
stateOrProvinceName     = match
organizationName        = match
organizationalUnitName  = optional
commonName              = supplied
emailAddress            = optional

[ policy_loose ]
# Allow the intermediate CA to sign a more diverse range of certificates.
# See the POLICY FORMAT section of the `ca` man page.
countryName             = optional
stateOrProvinceName     = optional
localityName            = optional
organizationName        = optional
organizationalUnitName  = optional
commonName              = supplied
emailAddress            = optional

[ req ]
# Options for the `req` tool (`man req`).
default_bits        = 8192
distinguished_name  = req_distinguished_name
string_mask         = utf8only

# SHA-1 is deprecated, so use SHA-2 instead.
default_md          = sha256

# Extension to add when the -x509 option is used.
x509_extensions     = v3_ca

[ req_distinguished_name ]
# See <https://en.wikipedia.org/wiki/Certificate_signing_request>.
countryName                     = Country Name (2 letter code)
stateOrProvinceName             = State or Province Name
localityName                    = Locality Name
0.organizationName              = Organization Name
organizationalUnitName          = Organizational Unit Name
commonName                      = Common Name
emailAddress                    = Email Address

# Optionally, specify some defaults.
countryName_default             = ES
stateOrProvinceName_default     = Spain
localityName_default            = Madrid
0.organizationName_default      = Acme S.A. (Intermediate CA)
organizationalUnitName_default  =
emailAddress_default            =

[ v3_ca ]
# Extensions for a typical CA (`man x509v3_config`).
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true
keyUsage = critical, digitalSignature, cRLSign, keyCertSign

[ v3_intermediate_ca ]
# Extensions for a typical intermediate CA (`man x509v3_config`).
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true, pathlen:0
keyUsage = critical, digitalSignature, cRLSign, keyCertSign

[ usr_cert ]
# Extensions for client certificates (`man x509v3_config`).
basicConstraints = CA:FALSE
nsCertType = client, email
nsComment = "OpenSSL Generated Client Certificate"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = clientAuth, emailProtection

[ server_cert ]
# Extensions for server certificates (`man x509v3_config`).
basicConstraints = CA:FALSE
nsCertType = server
nsComment = "OpenSSL Generated Server Certificate"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer:always
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth

[ client_server_cert ]
# Extensions for server certificates (`man x509v3_config`).
basicConstraints = CA:FALSE
nsCertType = client, server
nsComment = "OpenSSL Generated Server Certificate"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer:always
keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = clientAuth, serverAuth

[ crl_ext ]
# Extension for CRLs (`man x509v3_config`).
authorityKeyIdentifier=keyid:always

[ ocsp ]
# Extension for OCSP signing certificates (`man ocsp`).
basicConstraints = CA:FALSE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
keyUsage = critical, digitalSignature
extendedKeyUsage = critical, OCSPSigning
intermediate/openssl.conf

Crear y firmar el certificado del servidor, clientes o usuarios

Para cada servidor, cliente de servidor o usuario hay que crear nuevamente su clave privada y pública, crear la solicitud de firma o Certificate Sign Request (CSR) que se envía a la autoridad de certificación intermedia para que lo firme y esta devuelva un certificado firmado. En el caso de un certificado para un servidor se incluye en el campo Common Name o CN el nombre del dominio del servidor, un certificado multidominio contiene varios nombres de dominio para los que es válido en el campo Subject Alternative Names o SAN, los certificados también se pueden asociar a una dirección IP concreta pero lo habitual es utilizar nombres de dominio.

Para crear el certificado firmado por la CA intermedia nuevamente el primer paso es generar la clave privada y pública y la solicitud de firma de certificado.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#!/usr/bin/env bash
set -e

CA_PATH=../ca
CERTS_PATH=server-certs

export CA_DIR=$CA_PATH
export INTERMEDIATE_DIR=$CA_PATH/intermediate

mkdir -p $CERTS_PATH/certs $CERTS_PATH/csr $CERTS_PATH/private
cp openssl/server/openssl*.conf $CERTS_PATH/
cd $CERTS_PATH

# Server

openssl genrsa \
      -out private/consul-server.key.pem 8192
chmod 400 private/consul-server.key.pem

openssl req -config openssl-consul-server.conf \
      -key private/consul-server.key.pem \
      -subj "/C=ES/ST=Spain/L=Madrid/O=Acme S.A./CN=Consul Server" \
      -new -sha256 -out csr/consul-server.csr.pem
server-certs-1.sh

Una vez la CA intermedia firma la solicitud y genera el certificado se puede validar que la firma sea correcta.

1
2
$ openssl verify -CAfile $CA_PATH/intermediate/certs/ca-chain.cert.pem \
      certs/consul-server.cert.pem
server-certs-2.sh

Los clientes de un servidor como un navegador web cuando establecen la conexión segura comprueban que el nombre del dominio al que se ha realizado la solicitud esté contenido en los nombres de dominio y direcciones IP del certificado devuelto por el servidor y que esté firmado por una CA en la que se confía.

Para incluir en un certificados múltiples SAN ya sean dominios y direcciones IP es necesario indicarlo en el archivo de configuración al crear la solicitud en la sección alt_names y habilitar la extensión req_ext.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
[ req ]
default_bits       = 8192
distinguished_name = req_distinguished_name
req_extensions     = req_ext

[ req_distinguished_name ]
countryName                = Country Name (2 letter code)
stateOrProvinceName        = State or Province Name (full name)
localityName               = Locality Name (eg, city)
organizationName           = Organization Name (eg, company)
commonName                 = Common Name (e.g. server FQDN or YOUR name)

[ req_ext ]
subjectAltName = @alt_names

[alt_names]
DNS.1   = server.dc1.consul
DNS.2   = consul.service.consul
DNS.3   = localhost
DNS.4   = consul.192.168.33.10.xip.io
DNS.5   = consul.192.168.33.11.xip.io
DNS.6   = consul.192.168.33.12.xip.io
DNS.7   = consul.192.168.33.13.xip.io
DNS.8   = consul.192.168.33.14.xip.io
IP.1    = 127.0.0.1
IP.2    = 192.168.33.10
IP.3    = 192.168.33.11
IP.4    = 192.168.33.12
IP.5    = 192.168.33.13
IP.6    = 192.168.33.14
server/openssl-consul-server.conf

Inspeccionando la información del documento se observa que en la sección X509v3 Subject Alternative Name están incluidos los SAN adicionales.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
$ openssl x509 -noout -text \
      -in certs/consul-server.cert.pem
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: 4096 (0x1000)
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: C = ES, ST = Spain, O = Acme S.A., CN = Acme S.A. (Intermediate CA)
        Validity
            Not Before: Aug  6 22:39:48 2020 GMT
            Not After : Aug  5 22:39:48 2025 GMT
        Subject: C = ES, ST = Spain, L = Madrid, O = Acme S.A., CN = Consul Server
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                RSA Public-Key: (8192 bit)
                Modulus:
                    00:ef:5c:77:b4:e7:58:08:3f:d9:76:2c:67:52:f0:
                    37:c2:19:e6:e8:32:0e:b4:39:ea:77:b5:bb:e8:9c:
                    d0:75:62:90:d2:9d:53:bc:55:b1:4f:c8:09:69:41:
                    b1:8a:b4:39:5e:ba:8c:c5:b0:40:82:8c:4b:cb:f4:
                    b3:97:24:8d:3e:f6:81:24:80:7a:14:da:15:dc:8f:
                    ...
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Basic Constraints: 
                CA:FALSE
            Netscape Cert Type: 
                SSL Client, SSL Server
            Netscape Comment: 
                OpenSSL Generated Server Certificate
            X509v3 Subject Key Identifier: 
                40:A7:07:BE:51:F7:20:E6:6B:5C:0F:22:93:13:FF:07:9A:11:E5:E8
            X509v3 Authority Key Identifier: 
                keyid:0F:13:28:6E:13:8F:9D:25:7A:89:07:38:CA:05:F8:CA:49:47:57:62
                DirName:/C=ES/ST=Spain/L=Madrid/O=Acme S.A./CN=Acme S.A (CA)
                serial:10:00

            X509v3 Key Usage: critical
                Digital Signature, Non Repudiation, Key Encipherment
            X509v3 Extended Key Usage: 
                TLS Web Client Authentication, TLS Web Server Authentication
            X509v3 Subject Alternative Name: 
                DNS:server.dc1.consul, DNS:consul.service.consul, DNS:localhost, DNS:consul.192.168.33.10.xip.io, DNS:consul.192.168.33.11.xip.io, DNS:consul.192.168.33.12.xip.io, DNS:consul.192.168.33.13.xip.io, DNS:consul.192.168.33.14.xip.io, IP Address:127.0.0.1, IP Address:192.168.33.10, IP Address:192.168.33.11, IP Address:192.168.33.12, IP Address:192.168.33.13, IP Address:192.168.33.14
    Signature Algorithm: sha256WithRSAEncryption
         12:15:c8:74:8d:e4:5b:8a:13:2c:ae:42:1a:ca:11:aa:c0:89:
         de:29:25:6c:4f:b4:52:24:1a:cd:25:18:55:dd:6d:9d:ea:12:
         d9:f1:5d:f5:46:75:39:43:b9:6d:c0:a3:49:a9:80:63:ba:ea:
         bc:24:3b:49:e8:c3:9b:60:51:fc:bb:52:a4:61:18:ac:fe:58:
         3c:61:2c:af:0d:83:fa:d9:e5:ad:fa:73:10:9c:5b:f1:72:13:
         ....
server-certs-3.sh

Añadir el certificado de la CA en el navegador Firefox

Los navegadores incluyen los certificados de algunas autoridades de certificados en las que se confía. En el caso de crear una CA propia como lo mostrado en este artículo y un certificado para un servidor firmado por esta autoridad de certificados el navegador mostrará una advertencia indicando que el certificado presentado no es de confianza antes de permitir entrar al sitio web, con este mensaje el usuario es consciente de que el certificado del servidor no es de confianza y si el usuario lo desea se permite el acceso al sitio web. Aún así el navegador muestra una advertencia en el icono de seguridad del sitio web de que hay un problema con el certificado.

Advertencia con certificado no de confianza en Firefox

Para eliminar el mensaje de advertencia al acceder al sitio web y la advertencia del icono de seguridad del sitio web hay que instalar en el navegador el certificado de la CA raíz o intermedia. En el navegador web Firefox se importa un nuevo certificado de una CA en la que se confía desde la opción Preferencias > Privacidad y seguridad > Ver certificados > Autoridades > Importar en el navegador Chrome desde Configuración > Privacidad y seguridad > Gestionar certificados. Por defecto los navegadores web ya incorporan los certificados de varias CA importantes de internet.

Certificados de autoridades de certificación de confianza en Firefox

Una vez se importa el certificado de la CA el navegador muestra el icono de seguridad del sitio web con el icono sin advertencias indicando que no hay ningún problema de seguridad en la conexión con el sitio web, tampoco se muestra la página inicial de advertencia.

Certificado de confianza y conexión segura en Firefox

Revocar y renovar un certificado

Además de firmar y generar de certificados las funciones de una CA es revocar un certificado cuando se ha comprometido y ya no es de confianza por un problema de seguridad y renovar de los certificados cuando se fecha de validez expira.

Una vez se revoca un certificado hay dos formas en la que la CA permite conocer si un certificado ha sido revocado, con Certificate Revocation List (CRL) o Online_Certificate_Status_Protocol (OCSP) aunque CRL ha quedado en desuso y se prefiere OCSP. El problema del método CRL es que hay una latencia entre el momento en que se realiza la revocación esta ventana de tiempo no es deseable para evitar problemas de seguridad con la mayor inmediatez, la revocación se publica en el registro de CRL, su segundo problema es que en una CA grande con un número grande de certificados revocados el registro de CRL será también grande. OCSP también permite conocer si un certificado ha sido revocado, evita la latencia de CRL ya que no depende de un registro y requiere menos tráfico para realizar la comprobación ya que no requiere la descargar del registro CRL, pero introduce otros problemas como que debe soportar una número enorme de peticiones de comprobación de certificado ya que se hace una petición por cada visita a un sitio web, en el caso de una CA importante que tiene un número de certificados emitidos que usan sitios con mucho tráfico de internet es un problema. El segundo problema es una pérdida de privacidad para los usuarios ya que la CA al recibir una solicitud de comprobación de certificado por cada visita podría rastrear a los usuarios. Para evitar o al menos mitigar en gran medida los problemas de OCSP se ha desarrollado OCSP Stapling.

La CA guarda los certificados que emite, con OpenSSL en la carpeta newcerts con un número de serie, en el archivo a modo base de datos index.txt almacena entre otras cosas el número de serie y el Subject del certificado emitido. El comando para revocar un certificado incluye como argumento el certificado a revocar y opcionalmente el motivo de la revocación. El archivo index.txt se actualiza y en la entrada asociada al certificado se indica una R para indicar que ha sido revocado.

Si la revocación del certificado se realiza por un problema de seguridad en el que la clave privada y pública asociada al certificado han sido comprometidas es necesario revocar el certificado comprometido, generar un nuevo par de claves para evitar suplantaciones de identidad y emitir un nuevo certificado generado a partir de las nuevas claves privada y pública.

1
2
openssl ca -config intermediate/openssl.conf \
    -revoke intermediate/newcerts/1000.pem -crl_reason superseded
ca-intermediate-revoke.sh
1
2
3
4
5
6
7
R	250805223948Z	25080528054Z	1000	unknown	/C=ES/ST=Spain/L=Madrid/O=Acme S.A./CN=Consul Server
V	250805223951Z		1001	unknown	/C=ES/ST=Spain/L=Madrid/O=Acme S.A./CN=Consul Agent
V	250805223953Z		1002	unknown	/C=ES/ST=Spain/L=Madrid/O=Acme S.A./CN=Vault Server
V	250805223956Z		1003	unknown	/C=ES/ST=Spain/L=Madrid/O=Acme S.A./CN=Vault Agent
V	250805223958Z		1004	unknown	/C=ES/ST=Spain/L=Madrid/O=Acme S.A./CN=Nomad Server
V	250805224004Z		1005	unknown	/C=ES/ST=Spain/L=Madrid/O=Acme S.A./CN=Nomad Agent
V	250805224009Z		1006	unknown	/C=ES/ST=Spain/L=Madrid/O=Acme S.A./CN=UI Server
index.txt

Al revocar un certificado la CA regenera el CRL.

1
2
openssl ca -config intermediate/openssl.conf \
    -gencrl -out intermediate/crl/intermediate.crl
ca-intermediate-crl.sh

Los certificados se emiten con una de caducidad, llegado en el tiempo a la fecha de caducidad el certificado ya no se considera válido. En este caso hay que renovarlo. El servidor, cliente o usuario genera una nueva solicitud de certificado a partir de las mismas u otras nuevas claves privada y pública, la autoridad intermedia la recibe y realiza dos acciones: revoca el certificado anterior y genera un nuevo certificado a partir de la nueva solicitud de certificado. El comando de OpenSSL de la autoridad de certificados no permite que haya dos certificados con el mismo Subject válidos de modo que primero hay que revocar el certificado anterior. Los comandos son los mismos que los mostrados anteriormente para cada una de las acciones.

El código fuente completo del ejemplo puedes descargarlo del repositorio de ejemplos de Blog Bitix alojado en GitHub y probarlo en tu equipo ejecutando siguiente comando:
./ca.sh && ./server-certs.sh

Comparte el artículo: