Un certificado autofirmado puede ser útil para implementar SSL en entornos de desarrollo/testeo, o para el caso en que no se cuente con presupuesto suficiente para comprar uno firmado por una autoridad certificante de confianza (aunque algunas autoridades certificantes como namecheap ofrecen certificados económicos). Un certificado autofirmado no sirve para garantizar la identidad de un servidor, pero al menos provee un canal de comunicación seguro. Generar un certificado autofirmado también sirve para entender el proceso de creación y firma de un certificado y sus diferentes componentes.
Antes de comenzar, crear un directorio donde guardar certificados y sus claves:
mkdir certs cd certs/
Primer paso
Primero se debe generar una solicitud de firma de certificado (CSR, Certificate Signing Request). Esta contiene la información del certificado junto con la clave pública, y es lo que envía a las autoridades certificantes para ser firmada (generar el certificado de confianza). El archivo CSR utiliza generalmente el formato binario PKCS #10.
Con el siguiente comando, se genera una clave privada y una solicitud de firma de certificado con su correspondiente clave pública:
openssl req -new -nodes -keyout linuxito.key -out linuxito.csr -days 3650
Este comando solicita al usuario ingresar por entrada estándar cada uno de los campos del certificado, siendo el más importante el common name (CN), el cual debe coincidir con el nombre de host calificado del servidor (por ejemplo "www.linuxito.com") si se va a utilizar para proveer SSL en un servidor Web (HTTPS).
El parámetro -keyout
especifica el nombre de archivo para la clave privada, mientras que -nodes
indica que no se proteja con contraseña. Esto se hace por conveniencia ya que, de lo contrario, cada vez que se reinicie el servicio (que utilice dicho certificado) será necesario ingresar la contraseña (passphrase) para desencriptar la clave privada (lo cual entorpece la administración).
Por otro lado, el parámetro -out
indica el nombre de archivo para el CSR y -days
indica la duración de la validez del CSR. No confundir -days
con el período de validez del certificado una vez emitido. Este número sólo indica la cantidad de días que tiene la autoridad certificante para firmar la solicitud (luego del cual será necesario generar una nueva solicitud).
Al finalizar la ejecución se han generado dos archivos:
root@linuxito:~/certs# ll total 8.0K -rw-r--r-- 1 root root 1.1K Oct 1 11:15 linuxito.csr -rw-r--r-- 1 root root 1.7K Oct 1 11:15 linuxito.key
Por supuesto, al no proteger la clave privada con contraseña, será necesario ajustar sus permisos de lectura adecuadamente:
chmod 400 linuxito.keyout
De esta forma se mantiene a la clave privada en secreto:
root@linuxito:~/certs# ll total 12K -rw-r--r-- 1 root root 1.4K Oct 1 11:15 linuxito.crt -rw-r--r-- 1 root root 1.1K Oct 1 11:15 linuxito.csr -r-------- 1 root root 1.7K Oct 1 11:15 linuxito.key
El formato de archivo PKCS #10 se codifica en Base64:
root@linuxito:~/certs# cat linuxito.csr -----BEGIN CERTIFICATE REQUEST----- MIIC7jCCAdYCAQAwgagxCzAJBgNVBAYTAkFSMRUwEwYDVQQIDAxCdWVub3MgQWly ZXMxGDAWBgNVBAcMD0JhaMODwq1hIEJsYW5jYTERMA8GA1UECgwITGludXhpdG8x ETAPBgNVBAsMCFNpc3RlbWFzMRkwFwYDVQQDDBB3d3cubGludXhpdG8uY29tMScw JQYJKoZIhvcNAQkBFhhsaW51eGl0b0BvcGVubWFpbGJveC5jb20wggEiMA0GCSqG SIb3DQEBAQUAA4IBDwAwggEKAoIBAQC4l2EqXl9tu06QksmEupdPUc3mQaJhBaT0 id3FQlOUsR640DPzrDf24ikxhJ/IdtbQ7jH23O0tiXpqipZudkDM73fl4PUhiR2J CZarAG/1NFMItTgGqEaf+CepyDOWS5lHozun4/D16zM72H/wSR8LxF2sqDp+j8H+ n4FGPdGJ4lvCSIM2WTOzUqUAXFZNs/F7bsL81/1C3t485yXEso1nbz3eW7uFx/jq bNhjznkSIN72byx6jYPG4mS5C/ptgCGHzf+rAFdGbzWNQpnFvC/8OkLrN2piuqXy 3uxGjA4yT1cdZZmRYHF2QdCdg465pJTTrTQn8jbtiGx/QPf7xet5AgMBAAGgADAN BgkqhkiG9w0BAQUFAAOCAQEAS9Qj7nIFoW79+4Ag1wlOFKHjNT/Chf4iyYMpLe3P sCHnWAAEC3LDaX3eis5MsqqyoKGC9C0WM2tSizc8RBrmQ4GWU2SvRS7c+SOly/+/ nnbUYlxRsiScsEhm30Y3jhirxeCSZHUIxip2Ek8inoI8X72PnYCVAYkw6kPKM313 yazyoQQlP640sLfA8TImGDcf/AqZalvArA2PAqfHNQMjPdrjWSz94dOJFaXy0hy+ WngY7N+XehPbJ6Ddis/8rJ0TaeNugcprc1bmyTpoObVhE9qP4Qbn1Mb+L37yN8EB +Wz+7eYSf+pfUbYFnEbGmohAokjEaB3MB9Kgt0xUsF6uKA== -----END CERTIFICATE REQUEST-----
Es posible decodificarlo utilizando el comando base64
, aunque es un formato es binario:
grep -v "^--" linuxito.csr | base64 -d | tr -dc '[:print:]'
Por ejemplo:
root@linuxito:~/certs# grep -v "^--" linuxito.csr | base64 -d | tr -dc '[:print:]' 00010UAR10UBuenos Aires10UBaha Blanca10ULinuxito10USistemas10Uwww.linuxito.com1'0%*Hlinuxito*openmailbox****0"0*H0a*^_mNOQAaBS37)1v1-zjnv@w!o4S8F'3KG;3;I]:~F=[H6Y3R\VM{nB<%go=[lcy o,zdm!WFo5B/:B7jbF2OWe`qvA4'6l@y0*HK#rn N5?")-!Xri}L-3kR7<DCSdE.#vb\Q$HfF7du*vO"<_0C3}w%?42&7j[5#=Y,Zxz'inksV:h9a/~7l_QF@HhLT^(root@linuxito:~/certs#
Para interpretarlo correctamente es mejor utilizar el siguiente comando:
openssl req -subject -noout -in linuxito.csr
Por ejemplo:
root@linuxito:~/certs# openssl req -subject -noout -in linuxito.csr subject=/C=AR/ST=Buenos Aires/L=Bah\xC3\x83\xC2\xADa Blanca/O=Linuxito/OU=Sistemas/CN=www.linuxito.com/emailAddress=linuxito*openmailbox****
También es posible volcar toda la información del certificado (no sólo el subject) en formato de texto plano con el siguiente comando:
openssl req -text -noout -in linuxito.csr
Por ejemplo:
root@linuxito:~/certs# openssl req -text -noout -in linuxito.csr Certificate Request: Data: Version: 0 (0x0) Subject: C=AR, ST=Buenos Aires, L=Bah\xC3\x83\xC2\xADa Blanca, O=Linuxito, OU=Sistemas, CN=www.linuxito.com/emailAddress=linuxito*openmailbox**** Subject Public Key Info: Public Key Algorithm: rsaEncryption Public-Key: (2048 bit) Modulus: 00:b8:97:61:2a:5e:5f:6d:bb:4e:90:92:c9:84:ba: 97:4f:51:cd:e6:41:a2:61:05:a4:f4:89:dd:c5:42: 53:94:b1:1e:b8:d0:33:f3:ac:37:f6:e2:29:31:84: 9f:c8:76:d6:d0:ee:31:f6:dc:ed:2d:89:7a:6a:8a: 96:6e:76:40:cc:ef:77:e5:e0:f5:21:89:1d:89:09: 96:ab:00:6f:f5:34:53:08:b5:38:06:a8:46:9f:f8: 27:a9:c8:33:96:4b:99:47:a3:3b:a7:e3:f0:f5:eb: 33:3b:d8:7f:f0:49:1f:0b:c4:5d:ac:a8:3a:7e:8f: c1:fe:9f:81:46:3d:d1:89:e2:5b:c2:48:83:36:59: 33:b3:52:a5:00:5c:56:4d:b3:f1:7b:6e:c2:fc:d7: fd:42:de:de:3c:e7:25:c4:b2:8d:67:6f:3d:de:5b: bb:85:c7:f8:ea:6c:d8:63:ce:79:12:20:de:f6:6f: 2c:7a:8d:83:c6:e2:64:b9:0b:fa:6d:80:21:87:cd: ff:ab:00:57:46:6f:35:8d:42:99:c5:bc:2f:fc:3a: 42:eb:37:6a:62:ba:a5:f2:de:ec:46:8c:0e:32:4f: 57:1d:65:99:91:60:71:76:41:d0:9d:83:8e:b9:a4: 94:d3:ad:34:27:f2:36:ed:88:6c:7f:40:f7:fb:c5: eb:79 Exponent: 65537 (0x10001) Attributes: a0:00 Signature Algorithm: sha1WithRSAEncryption 4b:d4:23:ee:72:05:a1:6e:fd:fb:80:20:d7:09:4e:14:a1:e3: 35:3f:c2:85:fe:22:c9:83:29:2d:ed:cf:b0:21:e7:58:00:04: 0b:72:c3:69:7d:de:8a:ce:4c:b2:aa:b2:a0:a1:82:f4:2d:16: 33:6b:52:8b:37:3c:44:1a:e6:43:81:96:53:64:af:45:2e:dc: f9:23:a5:cb:ff:bf:9e:76:d4:62:5c:51:b2:24:9c:b0:48:66: df:46:37:8e:18:ab:c5:e0:92:64:75:08:c6:2a:76:12:4f:22: 9e:82:3c:5f:bd:8f:9d:80:95:01:89:30:ea:43:ca:33:7d:77: c9:ac:f2:a1:04:25:3f:ae:34:b0:b7:c0:f1:32:26:18:37:1f: fc:0a:99:6a:5b:c0:ac:0d:8f:02:a7:c7:35:03:23:3d:da:e3: 59:2c:fd:e1:d3:89:15:a5:f2:d2:1c:be:5a:78:18:ec:df:97: 7a:13:db:27:a0:dd:8a:cf:fc:ac:9d:13:69:e3:6e:81:ca:6b: 73:56:e6:c9:3a:68:39:b5:61:13:da:8f:e1:06:e7:d4:c6:fe: 2f:7e:f2:37:c1:01:f9:6c:fe:ed:e6:12:7f:ea:5f:51:b6:05: 9c:46:c6:9a:88:40:a2:48:c4:68:1d:cc:07:d2:a0:b7:4c:54: b0:5e:ae:28
Con eso verificamos que la solicitud sea correcta.
Segundo paso
A continuación es posible enviar el CSR a una autoridad certificante para que lo firme y emita el certificado correspondiente. Sin embargo es posible también firmar la solicitud con su misma clave privada, generando así un certificado "autofirmado". Para ello ejecutar:
openssl x509 -req -days 3650 -in linuxito.csr -signkey linuxito.key -out linuxito.crt
El subcomando x509
se utiliza para firmar solicitudes y verificar certificados. La opción -req
indica que se intenta crear un certificado a partir de una solicitud desde el archivo especificado por -in
. El certificado será guardado con el nombre que indica -out
y será válido por -days
días a partir de la fecha actual del servidor. Por último, el parámetro -signkey
indica la clave con la que será firmado el certificado, la cual (en este ejemplo) es la propia clave privada del certificado emitido.
Con este comando se genera el certificado autofirmado linuxito.crt
:
root@linuxito:~/certs# ll total 12K -rw-r--r-- 1 root root 1.4K Oct 1 11:15 linuxito.crt -rw-r--r-- 1 root root 1.1K Oct 1 11:15 linuxito.csr -r-------- 1 root root 1.7K Oct 1 11:15 linuxito.key
Es posible verificar su validez mediante:
root@linuxito:~/certs# openssl x509 -subject -issuer -enddate -noout -in linuxito.crt subject= /C=AR/ST=Buenos Aires/L=Bah\xC3\x83\xC2\xADa Blanca/O=Linuxito/OU=Sistemas/CN=www.linuxito.com/emailAddress=linuxito*openmailbox**** issuer= /C=AR/ST=Buenos Aires/L=Bah\xC3\x83\xC2\xADa Blanca/O=Linuxito/OU=Sistemas/CN=www.linuxito.com/emailAddress=linuxito*openmailbox**** notAfter=Sep 28 15:15:34 2025 GMT
Queda claro que el certificado es autofirmado al notar que el subject ("asunto" o "sujeto" del certificado) coincide con el issuer (emisor del certificado, quien lo firma). El certificado expira el 28 de septiembre de 2025 pues se ha utilizado la cantidad de días 3650
al momento de firmarlo.
Ya tenemos listo nuestro certificado autofirmado en dos simples pasos.
El certificado se emite en el formato binario DER (Distinguished Encoding Rules), codificado también en Base64:
root@linuxito:~/certs# cat linuxito.crt -----BEGIN CERTIFICATE----- MIIDzjCCArYCCQCIkWJuDyz+qjANBgkqhkiG9w0BAQUFADCBqDELMAkGA1UEBhMC QVIxFTATBgNVBAgMDEJ1ZW5vcyBBaXJlczEYMBYGA1UEBwwPQmFow4PCrWEgQmxh bmNhMREwDwYDVQQKDAhMaW51eGl0bzERMA8GA1UECwwIU2lzdGVtYXMxGTAXBgNV BAMMEHd3dy5saW51eGl0by5jb20xJzAlBgkqhkiG9w0BCQEWGGxpbnV4aXRvQG9w ZW5tYWlsYm94LmNvbTAeFw0xNTEwMDExNTE1MzRaFw0yNTA5MjgxNTE1MzRaMIGo MQswCQYDVQQGEwJBUjEVMBMGA1UECAwMQnVlbm9zIEFpcmVzMRgwFgYDVQQHDA9C YWjDg8KtYSBCbGFuY2ExETAPBgNVBAoMCExpbnV4aXRvMREwDwYDVQQLDAhTaXN0 ZW1hczEZMBcGA1UEAwwQd3d3LmxpbnV4aXRvLmNvbTEnMCUGCSqGSIb3DQEJARYY bGludXhpdG9Ab3Blbm1haWxib3guY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A MIIBCgKCAQEAuJdhKl5fbbtOkJLJhLqXT1HN5kGiYQWk9IndxUJTlLEeuNAz86w3 9uIpMYSfyHbW0O4x9tztLYl6aoqWbnZAzO935eD1IYkdiQmWqwBv9TRTCLU4BqhG n/gnqcgzlkuZR6M7p+Pw9eszO9h/8EkfC8RdrKg6fo/B/p+BRj3RieJbwkiDNlkz s1KlAFxWTbPxe27C/Nf9Qt7ePOclxLKNZ2893lu7hcf46mzYY855EiDe9m8seo2D xuJkuQv6bYAhh83/qwBXRm81jUKZxbwv/DpC6zdqYrql8t7sRowOMk9XHWWZkWBx dkHQnYOOuaSU0600J/I27Yhsf0D3+8XreQIDAQABMA0GCSqGSIb3DQEBBQUAA4IB AQBZxp1RPFKmizVxmg99Hev1FpaH5SzDq7IYsvZAtRK/2zSKGZ2qdZ1i18xTSbz2 m51b+Epp0Ws+OPLyUG7Zh4FzPnstnQr9W3WeeiedDrksZfrW78pjgaeAZHBKxeH+ eJoeQ9BalgS4n1EFJPZYfWDI/U2fcw+5GIUndUQB1oBVhYBZQohdGXHf2YYo3sH0 GRmxGYhUchQzCuFbiNWJkDk3OVYowil4iR5pNM8NGFwQtv+NGGFiOvTG51hQjB2r RBfwRrExxXMtEHcglx/gLbdz7H2uffsX14S6jr185EWG6lnjKdwY4gP4t72o1crc Ja3iVO4NrkbxCjtpYQEOFags -----END CERTIFICATE-----
Al igual que el CSR, es posible decodificarlo con base64
.
Cómo instalar un certificado SSL en Nginx
Para instalar un certificado SSL en un servidor Web Nginx se debe crear en la configuración una nueva sección servidor dentro del protocolo "http" que incluya los siguientes parámetros:
server { listen 443 ssl; ssl_certificate linuxito.crt; ssl_certificate_key linuxito.key; ssl_session_cache shared:SSL:1m; ssl_session_timeout 5m; ssl_ciphers HIGH:!aNULL:!MD5; ssl_prefer_server_ciphers on; //... }
Luego copiar el certificado y su clave privada al directorio de configuración de Nginx:
cp linuxito.crt linuxito.key /usr/local/nginx/conf/
Por último, se debe otorgar permiso de lectura (tanto al certificado como a la clave privada) para el usuario con el que corre Nginx.
Más información
man openssl man req man x509
Referencias