JASoft.org

El blog de José Manuel Alarcón Aguín. Programación web y mucho más...

MENÚ - JASoft: JM Alarcón

Cómo generar certificados HTTPS para desarrollo local que no produzcan errores

Ya hace mucho tiempo que la Web se ha vuelto "segura", con la lista de sitios que utilizan HTTPS creciendo cada día y alcanzando un porcentaje muy alto del total.

Además de los sitios y aplicaciones que están en producción y utilizan HTTPS, el uso de conexiones seguras se está volviendo imprescindible también a la hora de desarrollar. El principal motivo es que cada día más APIs de HTML5 requieren el uso de HTTPS para poder funcionar. Por ejemplo, la API de geolocalización, la de notificaciones o la de service workers entre otras muchas. Debido a ello, si necesitamos desarrollar aplicaciones con ciertas características, no nos queda más remedio que utilizar también HTTPS en nuestros equipos de desarrollo para poder probar y afinar el código.

Hace poco os contaba cómo podías solucionar en parte esta necesidad gracias a una interesantísima herramienta llamada ngrok que lo que hace es exponer hacia Internet cualquier sitio web local, de modo que lo pruebas en tu máquina pero saliendo a Internet y volviendo a entrar en ella desde un dominio externo.

ngrok es una utilidad genial y con muchas aplicaciones, pero ¿no sería mejor para desarrollar poder probar directamente contra localhost con HTTPS y sin necesidad de una vuelta tan grande? Es más, ¿no sería incluso mejor si pudiésemos desarrollar usando en local el mismo dominio que tendrá la aplicación final (o incluso uno inventado) con conexiones seguras incluidas?

Te voy a contar cómo puedes montar un entorno con estas características de manera sencilla en cualquier sistema operativo de escritorio (Windows, Mac y Linux).

El problema con los certificados HTTPS auto-firmados para localhost

Crear un certificado HTTPS para usar con el "dominio" localhost es bastante sencillo de conseguir en la mayor parte de los servidores web que se usan en producción. Por ejemplo en nginx o en Apache en Linux o Mac gracias a OpenSSL y también en Windows con Internet Information Server.

Estos certificados en realidad no son válidos ya que no están firmados por una entidad certificadora de confianza (se auto-firman por la propia máquina local), y cuando nos conectamos a un sitio web local que los utilice, pasa esto:

Nos sale una advertencia del navegador y tenemos que desplegar una zona oculta y seguir adelante. Esto en Chrome. En Firefox es incluso más complicado. Una vez que lo aceptamos ya no vuelve a salir mientras no cerremos el navegador, pero tenemos el recordatorio constante en la barra de tareas de que el certificado no es válido:

Sería mucho mejor tener un certificado verdaderamente válido para localhost. No solo eso, como decía antes, sería genial poder usar directamente el dominio real de la aplicación en local, y dotarlo de un certificado HTTPS válido también.

Vamos a ver cómo lograrlo gracias a una pequeña utilidad.

Crea tu propia entidad certificadora "virtual" con un solo comando

mkcert es una pequeña utilidad creada por el "crack" programador italiano Filippo Valsorda. Filippo ha trabajado en Cloudflare en programación relacionada con la criptografía, y actualmente está en Google en Nueva York en el equipo del lenguaje Go y en proyectos de seguridad y criptografía.

En junio de 2018 creó la utilidad llamada mkcert, que es gratuita y Open Source. mkcert permite crear certificados digitales para cualquier dominio, incluido localhost, que son siempre válidos para usar en la máquina local.

Lo consigue usando un truco interesante: en lugar de generar certificados auto-firmados como los que hemos visto, crea una autoridad certificadora "virtual" local, que se añade a las entidades raíz de confianza del sistema. Los certificados que genera van firmados por esta autoridad local, y como el sistema confía en ellos, tu navegador los ve como un certificado normal y corriente y muestra el iconito del candado de confianza. Fuera de tu máquina no valdrán para nada, pero en local son certificados de tanta confianza como cualquier otro. Justo lo que queremos para poder desarrollar en local sin problema.

¡Estupendo, vamos a probarlo!

Instalando la entidad certificadora "virtual" con mkcert

El uso de mkcert no podría ser más sencillo. Lo único que hay que hacer es descargar el ejecutable apropiado para tu sistema operativo desde la zona de "releases" del proyecto en Github. Por ejemplo, en mi caso la versión para Windows:

Descargas disponible para mkcert

Este ejecutable es ya el programa. No tiene dependencias ni necesita instalación. Es descargar y usar, lo cual es muy de agradecer. Eso sí, por sencillez de uso yo le cambio el nombre por defecto (que tiene la plataforma y la versión) y le dejo simplemente mkcert.exe. Cópialo a una carpeta donde lo tengas a mano para cuando lo necesites.

Para utilizarlo debes abrir una línea de comandos en Windows, o un terminal si estás en Mac o Linux. Ni siquiera necesitas elevar los privilegios para usarlo.

OJO: en Windows la protección de seguridad Smart Screen, al no identificar el programa, saca un aviso de que puede ser peligroso utilizarlo. Lo puedes ejecutar igual pulsando sobre el enlace y luego sobre la opción de continuar de todos modos:

Smart Screen en acción

Si lo pasas por VirusTotal refrendará que es un programa inocuo:

El programa no marca ningún positivo en VirusTotal.com

Lo primero que debes hacer es instalar la entidad certificadora "virtual" que se usará para gestionar los certificados. Esto solo tienes que hacerlo una vez, luego ya no vuelve a ser necesario. Para ello escribe:

mkcert -install

Y el sistema te mostrará un aviso de seguridad indicándote de que se va a instalar un certificado raíz de confianza para tu entidad certificadora. Aceptas y listo.

Animación que muestra la ejecución del comando y el aviso de seguridad

En Windows puedes comprobar que el certificado raíz está instalado haciendo lo siguiente:

  1. Busca la utilidad mmc.exe (la Microsoft Management Console) y ejecútala (necesitarás privilegios de administrador).
  2. Añade el complemento de certificados para el usuario actual desde el menú Archivo tal y como se muestra en esta animación:

Animación que muestra cómo añadir el complemento a MMC

3- Si ahora vas al nodo Trusted Root Certificate Authorities y ves los certificados, verás uno cuyo nombre empieza por "mkcert", que es el de la autoridad raíz virtual. Si haces doble-clic sobre él para examinarlo verás que su utilidad es la de firmar certificados:

Muestra el certificado raíz en MMC

Muestra el certificado raíz y sus propiedades

¡Genial, todo correcto! Ahora vamos a generar un certificado, que es lo que necesitamos.

Generando certificados con mkcert

Hacerlo es muy sencillo: basta con ejecutar mkcert seguido del nombre o nombres de dominio para los que queremos generar certificados. Por ejemplo, para un certificado válido para localhost:

mkcert localhost

Esto genera por defecto un certificado digital y un archivo de clave privada en formato PEM, muy común y que contiene la información en formato de texto codificada como Base64.

Este tipo de certificados son los más comunes en servidores en Mac o Linux y será lo que necesitas si estás en estos sistemas o si usas Apache o nginx. Sin embargo, para Windows deberías generar el certificado en formato PKCS 12, que guarda la información protegida con una contraseña. Para ello solo tienes que usar el parámetro -pkcs12, así:

Generación del certificado en formato PKCS 12

Esto generará el certificado digital en un único archivo con extensión .p12 que ya contiene tanto el certificado como la clave privada para encriptación.

Del mismo modo que lo haces para localhost, también puedes generar certificados para cualquier otro dominio, de modo que luego puedas simular que tu servidor local es dicho dominio, y así desarrollar, incluso, usando el dominio final que tendrá la web o la aplicación:

mkcert localhost www.dominio.com otrodominio.es

Como ves, se pueden especificar varios certificados en el mismo comando y se generará un único certificado para todos ellos.

Con esto conseguiremos disponer de certificados HTTPS que nos valen exactamente igual que certificados reales, solo que será nuestra máquina la única que los de por válidos.

Gracias a ellos podremos desarrollar en local del mismo modo que si estuviésemos trabajando contra el servidor real, lo cual es una gran ventaja.

Nota importante: aunque los certificados funcionan sin problema con los navegadores basados en Blink/Webkit como Chrome, Opera o Safari, Firefox no usa el registro de certificados del sistema, sino uno propio. Por lo tanto en Firefox no te funcionará de entrada. Para solucionarlo solo tienes que importar el certificado raíz de mkcert a Firefox. Puedes hacerlo con la utilidad de línea de comandos de Firefox, certutil, o más fácilmente a mano (ya que solo hay que hacerlo una vez) yendo a las opciones de seguridad de este navegador y en "Ver certificados" pestaña autoridades, importarlo allí desde tu carpeta de ajustes de aplicaciones para el usuario actual, como se ve en esta pequeña animación:

Ahora lo único que nos faltaría es incorporarlos a la lista de los certificados de la máquina y asignarlos a un sitio web. Esto dependerá de tu sistema operativo y del servidor web que utilices.

En mi próximo post te explicaré cómo puedes usar estos certificados con Internet Information Server Express (IIS Express) en Windows, que no es una cosa muy directa que digamos.

Mientras tanto ¡espero que este post te haya resultado útil!

¿Este post te ha ayudado?, ¿has aprendido algo nuevo? Pues ¡ayúdame a ayudar a otros! No te costará nada y puedes conseguir premio. Es muy importante. Pulsa para saber más...
José Manuel Alarcón José Manuel Alarcón
Fundador de campusMVP.es, el proyecto de referencia en formación on-line para programadores en lengua española. Autor de varios libros y cientos de artículos. Galardonado como MVP de Microsoft desde 2004. Gallego de Vigo, amante de la ciencia y la tecnología, la música y la lectura. Ayudando a la gente en Internet desde 1996.
Descarga GRATIS mi último libro (no técnico): "Tres Monos, Diez Minutos".
Banner

Comentarios (24) -

Excelente artículo y muy útil para desarrollar en local simulando un dominio con https, ahora que Google condiciona por ejemplo a los sitios web que cuenten con estos certificados ssl.

Responder

Gracias por el aporte. Muy didáctico y práctico.Tan sólo una duda ¿ el certificado que genera se puede incluir en el keystore del
jdk\bin de Java ?

Un saludo.

Responder

by Jose M. Alarcon

Hola Jesús:

No veo por qué no, usando la herramienta Keytool y teniéndolo en formato .cer es cuestión de hacer una llamada por línea de comandos.

Te he buscado cómo hacerlo en Google:

www.ibm.com/.../wave_appf.html

Saludos!

Responder

Para XAMPP Windows 10:

mkcert -install
mkcert localhost "*.dominio.com"
copy "localhost+1.pem" C:\xampp\apache\conf\ssl.crt\server.crt
copy "localhost+1-key.pem"  C:\xampp\apache\conf\ssl.key\server.key

Para Debian 10:

cd /root/mkcert

systemctl stop apache2

mv /etc/ssl/certs/ssl-cert-snakeoil.pem /etc/ssl/certs/ssl-cert-snakeoil.pem.bak
mv /etc/ssl/private/ssl-cert-snakeoil.key /etc/ssl/private/ssl-cert-snakeoil.key.bak

cp "localhost+1.pem" /etc/ssl/certs/ssl-cert-snakeoil.pem
cp "localhost+1-key.pem" /etc/ssl/private/ssl-cert-snakeoil.key

chown root:ssl-cert /etc/ssl/private/ssl-cert-snakeoil.key
chmod 640 /etc/ssl/private/ssl-cert-snakeoil.key

systemctl start apache2

Responder

Hola, buen articulo
Como se cual es la clave del certificado P12
?

Gracias

Responder

by Jose M. Alarcon

Hola Iván:

Si te fijas te la dice al terminar de generarlo, en la línea de comandos. Por defecto es:

changeit

Saludos!

Responder

Hola, y como lo utilizo en windows 7 xampp?

Responder

Julmer Olivero

Si quisiera usarlo para el localhost que monta nodeJS como seria la mejor forma de hacerlo?

Responder

by Jose M. Alarcon

Hola:

Es otra cosa diferente a lo que explico en este post y en el de IIS siguiente a este, pero lo básico sería:

Tienes que generar un certificado y una clave privada con mkcert, en lugar de un certificado PKCS12, para lo cual necesitas usar los parámetros -cert-file y -key-file de mkcert:

mkcert localhost -cert-file certificado.cert -key-file clave_privada.key

Una vez generados a sendos archivos, en Node.js, si usas el módulo de HTTPS nativo es decirle que los use y listo:

const https = require('https')
const fs = require('fs')

https.createServer({
  key: fs.readFileSync('clave_privada.key'),
  cert: fs.readFileSync('certificado.cert')
}, app).listen(433, () => {
  console.log('Escuchando en el puerto 433...')
})

Y podrías conectarte con HTTPS.

Saludos.

Responder

HERMENEGILDO

Hola primero gracias por el post, una pregunta al generar el certificado como indicas me genera un dos archivos (localhost+4.pem , localhost+4-key.pem), mi duda es los archivos .key y .cert como los obtengo.

Responder

by Jose M. Alarcon

mmm, está en el comentario al que me respontes:

mkcert localhost -cert-file certificado.cert -key-file clave_privada.key

com esto te genera tanto el certificado como la clave privada en los archivos que le indiques.

Saludos.

Responder

Ivan Ferrer

Infinitas gracias. Tanto que se facilita la creación web con gestores de paquetes, con mil y una librerías que te hacen la vida más fácil, IDEs varios... tan sencillo que parece todo al menos de primeras, pero te pones a probar de hacer tu flamante primera PWA en tu casa, en localhost y resulta que no puedes ni empezar por culpa del tema https que el navegador te tira en las narices a la primera de cambio. Aún no he probado el certificado/r pero por lo que cuentas funcionará de maravilla.
Gracias por contarlo tan fácil y por traernos una utilidad que lo hace tan fácil, casi para niños.
Odio amanecer un día inspirado a desarrollar algo y de pronto tener que pelear con la línea de comandos para un asunto que no tiene nada que ver con el proyecto, mientras veo que toda aquella inspiración se esfuma por la ventana. Al final te desesperas y abandonas. Como si un dia te arrancas a pintar un cuadro por hobby y no puedes ni empezar porque los lienzos que tienes no están certificados o los pinceles habría que dejarlos macerar un mes para que empapen pintura!!
Saludos

Responder

Hola, genial el articulo. seguí todos los pasos pero mi duda es la siguiente o quizás tengo una confusión..

Logre generar el certificado pero este igual tengo que configurarlo en el server.xml del tomcat ?

a modo de ejemplo:

    <Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
               maxThreads="150" SSLEnabled="true" scheme="https" secure="true"
         keystoreFile="C:\Program Files\Apache Software Foundation\Tomcat 8.0\key\localhost.p12"
         keystorePass="changeit"
         clientAuth="false" sslProtocol="TLS" />


(dentro de la carpeta raíz del tomcat me cree otra carpeta llamada key)


*trabajo con tomcat 8 y java 8

mi objetivo también es poder trabajar con https con un certificado valido en localhost..

Saludos!!

Responder

by Jose M. Alarcon

Hola Alex:

Sí, hay que instalarlo en tu servidor local favorito, como comento al final del artículo. Yo no tengo experiencia con Tomcat, así que no sé qué decirte al respecto de cómo hacerlo en ese servidor (aquí hay instrucciones y parece sencillo: www.thesslstore.com/.../) , pero tengo un artículo escrito a continuación de este (y enlazado al final) que explica cómo hacerlo en IIS.

Saludos.

Responder

Gracias Jose.

Consulta: Todavía estoy algo confundido...
Con el "mkcert" se supone que se genera un certificado autorizado?  (Al menos para ambiente localhost)

Si es así, se supone que solo tendría que seguir estos pasos de la pagina oficial de tomcat?

(Ver la siguiente pestaña)
"Installing a Certificate from a Certificate Authority"

tomcat.apache.org/.../ssl-howto.html

por lo que veo se usa el formato   .csr     con la herramienta "mkcert"  puedo generar ese tipo de formato?

Saludos!!

Responder

by Jose M. Alarcon

Hola:

Los CSR no son certificados. Son peticiones de firma de certificados. Es un paso que sigues para solicitar un certificado a un certificador y contienen la clave pública del certificado que quieres generar, habiendo generado la pareja previamente en el servidor. Puedes ver más aquí: en.wikipedia.org/wiki/Certificate_signing_request

A partir de ese CSR se genera el certificado en el formato que sea, que es lo que instalas. Con mkcert no necesitas el CSR ya que se encarga de todo pues es en local. Lo único que tienes que hacer es generar el certificado con mkcert tal y como explico, solo que si es para Linux el formato más apropiado no es el PKCS12 que uso yo para Windows (que es lo que uso y lo que explico en el post) sino, por lo que he visto (ya te digo que yo no uso Tomcat) en formato PKCS7. En el enlace que te puse en mi respuesta anterior te explica cómo convertir el certificado .cer que genera mkcert por defecto al formato .p7b que necesitas y cómo instalarlo.

Así que solamente tienes que generar un nuevo certificado con mkcert, convertirlo a .p7b con openssl e instalarlo en Tomcat.

Pero no te puedo ayudar más allá de esto.

Si lo resuelves así o con algún detalle extra coméntalo aquí para que le sirva a más gente. Gracias.

Saludos.

Responder

Hola Jose:

Adjunto la solución :
En mi caso es Para windows 10 64 bit,   
Use Tomcat 8.5 y jdk 1.8
Versión exacta(apache-tomcat-8.5.34 ,   jdk-8u181-windows-x64)



El certificado lo genere de la misma forma:

mkcert -pkcs12 localhost

Luego el certificado lo deje en la siguiente RUTA : C:\Program Files\Apache Software Foundation\Tomcat 8.5\conf\

y desde CMD como Administrador posicionado en la misma RUTA: C:\Program Files\Apache Software Foundation\Tomcat 8.5\conf\

(Para Convertir el fichero p12 a formato JKS)
ejecute lo siguiente:

keytool -importkeystore -deststorepass changeit -destkeystore localhost.jks -srckeystore localhost.p12 -srcstoretype PKCS12

La clave es la por defecto:  changeit

y finalmente configurar el tomcat en el archivo server.xml

Después del siguiente código: (como referencia...)    <Connector port="8090" protocol="HTTP/1.1"
                           connectionTimeout="20000"
                           redirectPort="8443" />

Agregar lo siguiente:

    <Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
               maxThreads="150" SSLEnabled="true">
        <SSLHostConfig>
            <Certificate certificateKeystoreFile="conf/localhost.jks"
                         type="RSA" />
        </SSLHostConfig>
    </Connector>



  Reiniciar tomcat.
  Probar si esta todo OK entrando a la siguiente URL:
    
    https://localhost:8443
  
  Si Aparece el símbolo del candado sin ninguna advertencia significa que esta todo OK.

Saludos!.

Responder

by Jose M. Alarcon

Genial! gracias por compartir.

Responder

Buen día estimado colaborador, es muy instructivo lo que indicas en este post, solo me falta aprender a configurarlo/instalarlo en Apache, soy novato en esto y te agradecería un mundo si me enseñas como hacerlo

Responder

Alberto Fernández

Hola. Tengo un sitio web sirvo desde mi propia PC (está encendida el 80% del día) con nginx, contraté servicio de dns para que mi página tenga un nombre, abrí el puerto que uso en nginx desde el router y mi página es totalmente visible para cualquier persona de este bendito planeta.
Peeero, Google se muestra remiso a admitirlo, debido a que mi página no es segura.
El certificado generado y explicado aquí (ya hice todo sin problemas), sirve para nginx pueda servir mi web de modo seguro?
Alguna ayuda, link o tutorial de como hacerlo... Ya me cansé de googlear, y no encuentro forma de hacerlo.
Gracias.

Responder

by Jose M. Alarcon

Hola:

Como se explica en el artículo, el programa instala un certificado raíz (que son aquellos en los que **tu equipo**, no el de los demás) confía, de modo que cuando te conectas para desarrollar el navegador confíe en él y puedas conectarte sin el molesto mensaje de que no se confía.

Si lo que quieres es montar un servidor hacia el exterior con un dominio propio tienes que montar un certificado digital real, de alguna entidad certificadora en la que confíen todos los navegadores por defecto. Mi recomendación: Let's Encrypt que son gratuitos y funcionan muy bien.

Saludos.

Responder

Alberto Fernández

Muchísimas Gracias José por tu respuesta.
Me descargué OpenSSL, y con este programa (que corre desde una consola como mkcert), en base al archivo P12 obtenido por tu tutorial, generé el archivo "pem" y el archivo "key" (los certificados), hice las modificaciones en la configuración de nginx, y resulta que anda perfecto.
Lo probé en IE, Chrome, Firefox, Opera.
TODOS me reconocen mi web como sitio seguro.
Peeero, cuando pedí a amigos (otras PC, otras IP) que prueben mi sitio, obtienen un error con el certificado de seguridad, evidentemente tal como tu lo explicas, es para uso local.
Así que haremos el trámite en Let's Encrypt.
Muchísimas Gracias!

Responder

Jose, muy buen post!

Tengo un problema de sertificados y quisiera saber si puedes ayudarme. Desde mi web que es https necesito generar un <iframe> Para llamar a un botón que se encuentra en mi ordenador. Y aquí el problema, en la web mi ordenador aparece como http://100.00.00.00:8088
Tengo alguna manera de obtener certificado y que mi puerto de entrada sea https??
Gracias y felicitaciones por el post

Responder

Alguien puede ayudarme?
Tenia un certificado PFX para IIS y pude realizar las conversiones de manera correcta.
El problema surge que conectandome a la web publicada de manera externa con HTTPS funciona bien, pero cuando trato de conectarme localmente (intranet con dominio) no logra conectarse ni con HTTPS ni con HTTP.

la web se accede desde un dominio gob.cl y el certificado PFX me proporcionaron para poder realizar las conversiones.
¿Tal vez tengoa que configurar algo ademas de lo que hice en el servidor NGINX o que más puede ser?

Responder

Agregar comentario