Crear una clave privada para un server y un certificate request en dos pasos

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.

La ventaja de hacer esto en dos pasos es que podemos generar la clave sin passphrase de modo tal de no tener que acceder a la consola cada vez que se reinicia el server (ojo que hay que cuidar mucho la clave privada, ya que no está encriptada).

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 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 SERIAL="00"

export KEY_EXT="key"
export REQ_EXT="csr"
export KEY_LENGTH="2048"

Generación de clave privada del server

Me aseguro de tener las variables de entorno seteadas y uso el siguiente comando para crear la clave privada:

# primero creo la clave privada
openssl genrsa -out ${DOMAIN}_${SERIAL}.${KEY_EXT} ${KEY_LENGTH}

Esto genera la clave privada sin pedir la passphrase:

Generating RSA private key, 2048 bit long modulus
....................................+++
.....................................................................................................+++
unable to write 'random state'
e is 65537 (0x10001)

esto generó en el directorio actual un archivo ${DOMAIN}_${SERIAL}.${KEY_EXT}. Con los datos del ejemplo sería www.example.org_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}_${SERIAL}.${KEY_EXT} /etc/ssl/private
sudo chmod -v 640 /etc/ssl/private/${DOMAIN}_${SERIAL}.${KEY_EXT}
sudo chown -v root:ssl-cert /etc/ssl/private/${DOMAIN}_${SERIAL}.${KEY_EXT}

Generación del pedido de firma de certificado

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

Automáticamente

Creamos variables de entorno con los datos que queremos 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 el pedido de firma de certificado

openssl req -utf8 -new -key ${DOMAIN}_${SERIAL}.${KEY_EXT} -keyform PEM\
  -out ${DOMAIN}_${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 -key ${DOMAIN}_${SERIAL}.${KEY_EXT} -keyform PEM\
  -out ${DOMAIN}_${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:

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ó un archivo con el mismo nombre que nuestro archivo de clave, pero con extensión .csr (certificate signing request) que es lo que se le debe enviar a la CA para que lo firme, generando así un certificado.

Esto generó en el directorio actual un archivo ${DOMAIN}_${SERIAL}.${REQ_EXT}, es decir, lo único distinto es la extensión. Con los datos del ejemplo sería www.example.org_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/CrearUnaClaveDeServidorYunPedidoDeCertificadoEnDosPasos (última edición 2011-12-05 08:15:33 efectuada por MarianoAbsatz)