Cuando estamos desarrollando una aplicación que utiliza certificados de cliente para autenticar a los usuarios debemos crear certificados de prueba para poder probar la aplicación, pero también se debe crear uno para utilizar con SSL en el Internet Information Server, y otro certificado que utilizaremos como entidad emisora de los certificados anteriores.
Para crear estos certificados de prueba utilizaremos la herramienta MakeCert, la cual crea archivos de certificado con sus pares de claves (pública y privada). Esta herramienta también asocia el par de claves al nombre especificado de una empresa y crea un certificado X.509 que enlaza el nombre especificado por un usuario con la parte pública del par de claves.
Cabe mencionar que esta aplicación, además de crear el archivo con el certificado, lo instala en uno de los repositorios de Windows, los cuales pueden verse, por ejemplo, desde el Internet Explorer, en el menú “herramientas”, “opciones de internet”, “contenido”, “certificados”, lo que abre una ventana como la que se muestra a continuación.
Esta es una de las herramientas que se incluyen en el Windows SDK, el cual viene con Visual Studio o puede bajarse de forma independiente de la siguiente dirección: http://msdn.microsoft.com/es-ar/windows/bb980924.aspx.
Como primer paso vamos a crear el certificado de la entidad emisora con los siguientes parámetros:
- Vamos a llamarlo “Scientia Root Auth” con la opción “-n” utilizando la nomenclatura definida en X.500
- Lo vamos a guardar en el repositorio personal (opción “-ss my”)
- Lo vamos a guardar a nivel de máquina (opción “-sr LocalMachine”)
- Vamos a utilizar el algoritmo SHA-1 para calcular el hash (opción “-a sha1”)
- Vamos a marcar la clave privada como exportable (opción “-pe”)
- Lo vamos a utilizar para firmar (opción “-sky signature”)
- Este certificado va a estar “autofirmado”, o sea, no va a ser creado por otra entidad emisora
Entonces, utilizando los parámetros descriptos en esta lista, el comando a ejecutar queda así:
makecert -pe -n "CN=Scientia Root Auth" -ss my -sr LocalMachine -a sha1 -sky signature -r "ScientiaRootAuth.cer"
Para confiar en este certificado, al ser autofirmado, tenemos que copiarlo al repositorio raíz de entidades de certificación de confianza (Trusted Root Certification Authorities), para lo cual vamos a utilizar otra herramienta que viene en el Windows SDK llamada “Certification Manager” (CertMgr). Esta herramienta puede utilizarse desde su interfaz gráfica o a través de la línea de comandos. Nosotros vamos a utilizarla a través de la línea de comandos para copiar el certificado:
certmgr -add -all -c "ScientiaRootAuth.cer" -s -r LocalMachine Root
Ahora vamos a crear el certificado para utilizar SSL en el Internet Information Server con el protocolo https:
- Vamos a marcar la clave privada como exportable (opción “-pe”)
- Vamos a utilizar la nomenclatura definida en X.500 para nombrarlo “localhost” (opción “-n”)
- Lo vamos a guardar en el repositorio personal (opción “-ss my”)
- Lo vamos a guardar a nivel de máquina (opción “-sr LocalMachine”)
- Vamos a utilizar el algoritmo SHA-1 para calcular el hash (opción “-a sha1”)
- Lo vamos a utilizar para intercambio de identidades (opción “-sky exchange”)
- Lo vamos a utilizar para autenticar el servidor (opción “-eku 1.3.6.1.5.5.7.3.1”)
- Vamos a utilizar como entidad emisora el certificado creado en el primer paso (opción “-in «Scientia Root Auth”)
- La cual está en el repositorio personal (opción “-is my”)
- A nivel de máquina (opción “-ir LocalMachine”)
- Establecemos el proveedor del CryptoAPI con la opción “-sp «Microsoft RSA SChannel Cryptographic Provider»”
- Y el tipo de de proveedor CryptoAPI con la opción “-sy 12”
Entonces, utilizando los parámetros descriptos en esta lista, el comando a ejecutar queda así:
makecert -pe -n "CN=localhost" -ss my -sr LocalMachine -a sha1 -sky exchange -eku 1.3.6.1.5.5.7.3.1 -in "Scientia Root Auth" -is my -ir LocalMachine -sp "Microsoft RSA SChannel Cryptographic Provider" -sy 12 localhost.cer
Ahora podemos configurar el Internet Information Server para que utilice este certificado. En este ejemplo vamos a utilizar el IIS versión 5.1, aunque esta tarea puede realizarse con cualquier versión. Desde las propiedades del sitio web, en la solapa “Seguridad de directorios”, vamos a ver una sección llamada “Comunicaciones seguras”.
Ahí vamos a poder pulsar en el botón “Certificado de servidor…” y se nos va a abrir un “wizard” para crear, elegir o importar un certificado. En este ayudante vamos a seleccionar “asignar un certificado existente” y, en el paso siguiente, vamos a elegir el certificado llamado “localhost” (el creado en el paso anterior), luego ingresaremos el puerto que utilizaremos para SSL (por defecto es el 443), y listo, finalizamos el ayudante y ya podemos utilizar https en nuestro IIS.
Ahora, si necesitamos requerir que el usuario ingrese un certificado para autenticarse o para leer los datos del mismo, tenemos que crearlo. Para esto volveremos a utilizar la herramienta MakeCert, pero con algunos parámetros distintos:
- Vamos a marcar la clave privada como exportable (opción “-pe”)
- Vamos a utilizar la nomenclatura definida en X.500 para ingresar el nombre del usuario, el país, la empresa, la unidad organizativa y el mail (opción “-n”)
- Lo vamos a guardar en el repositorio personal (opción “-ss my”)
- Como es un certificado personal lo vamos a guardar a nivel de usuario (opción “-sr CurrentUser”)
- Vamos a utilizar el algoritmo SHA-1 para calcular el hash (opción “-a sha1”)
- Lo vamos a utilizar para intercambio de identidades (opción “-sky exchange”)
- Lo vamos a utilizar para autenticación del cliente (opción “-eku 1.3.6.1.5.5.7.3.2”)
- Vamos a utilizar como entidad emisora el certificado creado en el primer paso (opción “-in «Scientia Root Auth”)
- La cual está en el repositorio personal (opción “-is my”)
- A nivel de máquina (opción “-ir LocalMachine”)
- Establecemos el proveedor del CryptoAPI con la opción “-sp «Microsoft RSA SChannel Cryptographic Provider»”
- El tipo de de proveedor CryptoAPI con la opción “-sy 12”
- Por último le vamos a establecerle 25000000 como número de serie (opción “-# 25000000”)
Ahora juntamos todos estos parámetros y el comando nos queda:
makecert -pe -n "CN=Gustavo Cantero, O=Scientia Soluciones Informaticas, OU=Desarrollo, E=g.cantero@Scientia.com.ar, C=AR" -ss my -sr CurrentUser -a sha1 -sky exchange -eku 1.3.6.1.5.5.7.3.2 -in "Scientia Root Auth" -is Root -ir LocalMachine -sp "Microsoft RSA SChannel Cryptographic Provider" -sy 12 -# 25000000 GustavoCantero.cer
Bien, ahora para que el IIS le pida este certificado al usuario tenemos que habilitar SSL en la carpeta o sitio donde necesitamos el certificado, y establecerle que el usuario puede o debe seleccionar un certificado de cliente para autenticarse. Esto se hace desde la misma solapa “Seguridad de directorios” de las propiedades del sitio (o carpeta del sitio), pero pulsando sobre el botón “Modificar” de la sección “Comunicaciones seguras”, ahí vamos a pulsar sobre “Requerir canal seguro (SSL)” para que sólo pueda utilizarse a través de https, y “Requerir certificados de cliente”, para que el usuario deba seleccionar un certificado.
Dependiendo de la versión de IIS y del sistema operativo también vamos a poder vincular los certificados del cliente a usuarios del dominio y otras opciones más avanzadas, las cuales exceden el propósito de este artículo.
Ahora, al acceder al sitio vamos a ver que nos muestra que tenemos un certificado en el cual no confiamos, esto es porque el certificado raíz no está en el repositorio de confianza del Internet Explorer. Para seguir podemos pulsar sobre “Continuar con este sitio”, y luego de esto el navegador va a abrir una ventana para que elijamos un certificado de cliente, y en esa ventana vamos a ver el último certificado que creamos.
Como último paso vamos a leer el certificado y a mostrar la información básica desde una página de ASP.NET con el siguiente código agregado en el evento Load de la página:
HttpClientCertificate objCert = Request.ClientCertificate; if (objCert.IsPresent) { if (objCert.IsValid) { System.Security.Cryptography.X509Certificates.X509Certificate2 objCert2 = new System.Security.Cryptography.X509Certificates.X509Certificate2(objCert.Certificate Response.Write("Persona = " + objCert.Subject + "<br/>"); Response.Write("Emisor = " + objCert.Issuer + "<br/>"); Response.Write("Válido desde = " + objCert.ValidFrom + "<br/>"); Response.Write("Válido hasta = " + objCert.ValidUntil + "<br/>"); Response.Write("¿Es válido ? = " + objCert.IsValid + "<br/>"); Response.Write("Tamaño de la clave = " + objCert.SecretKeySize + "<br/>"); Response.Write("Nombre del certificado del servidor = " + objCert.ServerSubject + "<br/>"); Response.Write("Emisor del certificado del servidor = " + objCert.ServerIssuer + "<br/>"); Response.Write("Número de serie = " + objCert.SerialNumber + " - " + int.Parse(objCert2.SerialNumber, NumberStyles.HexNumber) + "<br/>"); Response.Write("Hash = " + objCert.CertEncoding + "<br/>"); } else Response.Write("El certificado no es válido"); } else Response.Write("No se ha encontrado un certificado");
En el próximo artículo mostraré algunos usos más avanzados de los certificados desde .NET.