Crear una clave privada para un server y un certificate request en un paso

Esta es una tarea del comprador del certificado... el usuario que haga esto no debe ser el que esté configurado como Autoridad de Certificación (es decir, no debe tener seteada la variable ${OPENSSL_CONF} apuntando al openssl.conf de la CA.

Entorno y nombres de archivos para claves y certificados

Vamos a usar algunas variables de entorno para que los comandos nos sirvan en muchos casos. El nombre de los archivos va a tener el nombre del dominio, el protocolo para el cual lo usamos (podemos tener uno para HTTP, otro para SMTP y otro para IMAP), y un número de serie nuestro (para poder mantenerlo a medida que se van venciendo los certificados viejos y usando nuevos).

Supongamos que queremos generar la primera clave y certificado para el servidor web del dominio www.example.org, entonces creamos las variables de entorno:

# Si queremos un certificado para todos los subdominios de un dominio,
# acá pondríamos un NOMBRE LÓGICO para esto (ya que esto va a generar
# nombres de archivo):
# export DOMAIN="WILDCARD.example.org"
export DOMAIN="www.example.org"
export PROTOCOL="HTTP"
export SERIAL="00"

export KEY_EXT="key"
export REQ_EXT="csr"

Generación de clave privada del server y pedido de firma del certificado

Ahora vamos a crear una clave privada para nuestro server y un pedido de firma de certificado con nuestros datos asociados a dicha clave. Este pedido contiene la información que le cargamos y la clave pública asociada a dicha clave privada. La clave privada nunca sale de nuestro control (es decir, la CA nunca ve nuestra clave privada).

Automáticamente

Me aseguro de tener las variables de entorno generales seteadas y creo variables de entorno con los datos que quiero que aparezcan en el certificado:

export COUNTRY="AR"
# Si queremos un certificado para todos los subdominios de un dominio,
# acá pondríamos el WILDCARD '*' para esto (ya que esto va a generar
# el pedido de certificado en sí):
# export DOMAINNAME=*.example.org
# si $DOMAIN era un dominio, común y corriente, acá va exactamente lo mismo
export DOMAINNAME=$DOMAIN
export STATE="Mi Provincia"
export LOCALITY="Mi Ciudad"
export ORGANIZATION="El Nombre de mi Organización o Empresa"
export ORG_UNIT="Si quiero pongo el nombre de una subdivisión dentro de mi organización"
export EMAIL="webmaster@example.org"

Ahora corro el comando para generar la clave privada y el pedido de firma de certificado. La opción -nodes es para que no encripte la clave privada.

openssl req -utf8 -new -newkey rsa:1024 -nodes\
  -keyout ${DOMAIN}_${PROTOCOL}_${SERIAL}.${KEY_EXT} -keyform PEM\
  -out ${DOMAIN}_${PROTOCOL}_${SERIAL}.${REQ_EXT} -outform PEM \
  -subj "/C=${COUNTRY}/ST=${STATE}/L=${LOCALITY}/O=${ORGANIZATION}/OU=${ORG_UNIT}/CN=$DOMAINNAME/emailAddress=$EMAIL/"

Interactivamente

Si preferimos cargar los datos para el pedido de certificado en forma interactiva, entonces hacemos:

openssl req -utf8 -new -newkey rsa:1024 -nodes\
  -keyout ${DOMAIN}_${PROTOCOL}_${SERIAL}.${KEY_EXT} -keyform PEM\
  -out ${DOMAIN}_${PROTOCOL}_${SERIAL}.${REQ_EXT} -outform PEM

Esto va a arrancar el pedido de requerimiento en modo interactivo (pongo las respuestas en mayúsculas). Es obligatorio llenar:

Generating a 1024 bit RSA private key
.++++++
...++++++
unable to write 'random state'
writing new private key to 'www.example.org_HTTP_00.key'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:AR
State or Province Name (full name) [Some-State]:Ciudad Autónoma de Buenos Aires
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:NOMBRE DE MI ORGANIZACIÓN
Organizational Unit Name (eg, section) []:NOMBRE DEL ÁREA (SI QUIERO)
Common Name (eg, YOUR name) []:WWW.EXAMPLE.ORG
Email Address []:WEBMASTER@EXAMPLE.ORG

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

Salida

Cualquiera de los comandos openssl req de arriba (automático o interactivo), generó dos archivos con el mismo nombre y distinta extensión en el directorio actual.

Clave privada del server

El primer archivo es la clave privada del server con nombre ${DOMAIN}_${PROTOCOL}_${SERIAL}.${KEY_EXT}. Con los datos del ejemplo sería www.example.org_HTTP_00.key.

Este archivo es importante y /!\ SECRETO /!\ . Nadie lo debe poder ver ya que quien lo vea podrá impersonar nuestro server.

En el server normalmente se guarda en /etc/ssl/private, con dueño:grupo root:ssl-cert y permisos 640 (-rw-r-----). Si ya estamos en el servidor, esto podemos hacerlo así:

sudo cp -v ${DOMAIN}_${PROTOCOL}_${SERIAL}.${KEY_EXT} /etc/ssl/private
sudo chmod -v 640 /etc/ssl/private/${DOMAIN}_${PROTOCOL}_${SERIAL}.${KEY_EXT}
sudo chown -v root:ssl-cert /etc/ssl/private/${DOMAIN}_${PROTOCOL}_${SERIAL}.${KEY_EXT}

Pedido de firma de certificado

El segundo archivo es el pedido de firma del certificado con nombre ${DOMAIN}_${PROTOCOL}_${SERIAL}.${REQ_EXT}, es decir, lo único distinto en el nombre del archivo con la clave es la extensión. Con los datos del ejemplo sería www.example.org_HTTP_00.csr (.csr == certificate signing request).

{i} Este archivo es lo que hay que mandar a la Certification Authority para que genere un certificado y nos lo mande.

OpenSsl/CrearUnaClaveDeServidorYunPedidoDeCertificadoEnUnPaso (última edición 2008-11-20 11:29:39 efectuada por MarianoAbsatz)