Certificados Digitales de cliente en Windows 8

Hoy os traemos un post invitado escrito por Juan Manuel Servera. Juan Manuel (@jmservera) es Technical Manager en el MICTT de Baleares. Ha estado trabajando con Windows 8 desde las primeras versiones de pruebas, fue el primero en superar un Excellence Lab en España y de los primeros en publicar en la Windows Store con su app Finger Paint. Además gracias a él contamos con el Tutorial de creación de apps Metro para Windows 8 con Javascript, HTML5 y CSS3.

Juanma fue uno de los mentores del exitoso Megathon de Windows 8. En este artículo Juan Manuel nos hablará de como podemos incluir certificados digitales en nuestras aplicaciones.

Windows 8 incorpora un nuevo modelo de seguridad por aislamiento para sus apps. Permite a las aplicaciones ejecutarse a muy bajo nivel en el sistema operativo, manteniendo unas restricciones de acceso muy altas. Cualquier acceso a elementos importantes del sistema debe ser declarado por el desarrollador y luego permitido explícitamente por el usuario.

Este nuevo modelo implica que las aplicaciones ya no tienen pleno acceso a la infraestructura de clave privada y al almacén de certificados. Este hecho nos puede parecer una barrera, pero el equipo de WinRT, las API que utilizamos para programar en el nuevo modelo de aplicaciones, nos ha puesto muchas facilidades para poder utilizar los certificados de usuario.

¿Qué vamos a ver?

Este artículo está dividido en 3 partes, pues es una prueba de concepto completa que podremos hacer en nuestra máquina. Según sean los conocimientos del lector podrá saltarse alguno de los pasos:

  • Introducción a los certificados de usuario: breve, para saber de qué estamos hablando
  • Uso de certificados en las aplicaciones Windows 8
  • Creación de un servicio que acepte certificados para realizar pruebas

¿Qué voy a necesitar?

Introducción

Tipos de certificado

Podemos dividir los certificados digitales en tres tipos, dependiendo de dónde se utilicen:

  • Certificados de cliente: funcionan como un identificador digital que permite identificar a un usuario frente a otro usuario o dispositivo e incluso entre dispositivos en el caso de redes privadas virtuales, también los podemos utilizar para cifrar y firmar documentos.
  • Certificados de servidor: permiten asegurar que el servidor es de la compañía que dice ser. Además se utilizan para cifrar las comunicaciones, habitualmente con el protocolo SSL
  • Certificados de firma de código: que confirman que el software que descargas de internet es auténtico. Por ejemplo, el Windows Store se encarga de firmar nuestras apps con un certificado de autenticidad, es la versión digital del holograma que llevan los DVDs.

En este artículo nos vamos a centrar en los primeros, pues son los que utilizaremos en las aplicaciones Windows 8. El segundo tipo de certificados está relacionado con el primero, pues el envío del certificado de cliente hacia el servidor se realizará por un canal https.

El almacén de certificados

Los certificados digitales pueden estar almacenados físicamente en el disco duro del equipo o una tarjeta inteligente como el DNIe. Windows nos proporciona una capa de abstracción sobre los distintos contenedores llamada el almacén de certificados.

Este almacén está dividido en unos cuantos almacenes lógicos: el de usuario, el del equipo y los almacenes de servicio, uno por cada servicio. No me extenderé más sobre este tema, podemos leer todo lo necesario sobre los almacenes en Technet y en este artículo de MSDN.

Para abrir y visualizar el contenido de los almacenes, accedemos a ellos a través de la configuración del equipo:

image

Gestión de Certificados en eWindows 8

O bien, recurriendo directamente a nuestra vieja amiga la consola MMC; podemos añadir el complemento de certificados. Al abrir nos pedirá con qué grupo de certificados queremos trabajar:

image

Configuración del Complemento Certificados

Acceso al almacén de certificados

En las aplicaciones de escritorio tenemos una API rica de acceso al almacén de certificados, podemos listar los certificados del usuario, lanzar un diálogo de selección de certificado para que el usuario nos indique qué certificado es el adecuado e incluso añadir certificados al almacén si tenemos los permisos adecuados.

image

Selección de certificado en Windows

Sin embargo, en las aplicaciones estilo Windows 8 no contamos con esta API. Dadas las características especiales de dichas aplicaciones, no es posible listar los certificados que tenemos instalados en el equipo. Si ya tenemos un poco de experiencia con las aplicaciones en Windows 8 nos esperaremos encontrar una clase del tipo DigitalCertificatePicker o similar, de manera que el usuario seleccione el certificado y el sistema nos lo proporcione, pero tampoco encontraremos esa opción.

Certificados Digitales en aplicaciones estilo Windows 8

Las aplicaciones estilo Windows 8 se ejecutan dentro de un contenedor especial completamente aislado del resto de las aplicaciones. Nuestra aplicación tiene permisos de escritura en su contenedor aislado. Dentro del mismo tenemos un almacén de certificados privado para la aplicación y para el usuario que la está ejecutando; de esta manera, ninguna otra aplicación tiene acceso al almacén privado de nuestra aplicación y podemos almacenar aquí certificados descargados desde un servidor.

Adicionalmente, tendremos acceso de lectura a los certificados del equipo, pues muchos servicios SSL utilizan claves que normalmente están en dicho almacén para las conexiones https. Normalmente no tendremos que preocuparnos por estos certificados, pues el sistema se encargará de cargarlos automáticamente al realizar una conexión.

Certificados compartidos

Hay otro conjunto importante de certificados, los certificados de cliente, a los que sólo podremos acceder si solicitamos permiso. Como hemos visto antes, dentro de este almacén están los certificados de usuario instalados por el mismo, por ejemplo el certificado digital de usuario de la Fábrica Nacional de Moneda y Timbre que vamos a utilizar en los ejemplos.

Para poder utilizar un certificado de cliente instalado en el almacén personal del usuario o un certificado de una tarjeta inteligente, será necesario activar esta capacidad en el manifiesto de la aplicación:

image

Activar la capacidad de Certificados Compartidos

Una vez activada esta capacidad, nuestra aplicación tendrá acceso a los certificados de usuario, tanto los instalados en el equipo como los que provengan de una tarjeta inteligente. Esto nos será muy útil cuando necesitemos autentificarnos ante un servicio web. Por ejemplo, para acceder a la administración pública por internet hace falta un certificado de usuario para identificarnos (el certificado de la FNMT).

Al ejecutar una consulta https que requiera autentificación de usuario mediante certificado, el sistema determinará qué certificado de la lista de certificados compartidos es el más adecuado. Si tiene dudas preguntará. Por ejemplo, con el siguiente código accedemos a la información privada del catastro utilizando nuestro certificado de la FNMT, si lo tenemos:

  1: new WinJS.xhr({ 
  2:     url: "https://www.sedecatastro.gob.es/CYCTitular/OVCAccTit.aspx?Dest=1" 
  3: }).then(function (e) { 
  4:     contenido.textContent = e.responseText; 
  5: }, 
  6: function (ex) { 
  7:     contenido.innerHTML = toStaticHTML(ex.response); 
  8: });

Al realizar la solicitud, el sistema buscará dentro de los certificados del usuario si hay alguno que coincida con el que pide el sitio web. En el caso de que haya varios certificados válidos para el sitio nos solicitará cual queremos utilizar:

image

Si sólo hay uno se saltará el paso anterior.

Además, solicitará permiso del usuario para utilizarlo, por defecto está marcada la casilla de mantener siempre el permiso, para evitar estar molestando al usuario continuamente:

image

Cuando le demos permiso, la solicitud https continuará de manera transparente para nosotros.

Aquí se acabaría le artículo, pero como ha sido demasiado fácil vamos a complicarlo un poco creando un servidor de pruebas, que nos servirá también para discutir otro día sobre cómo descargar y almacenar certificados en nuestra aplicación.

Servicio web para realizar pruebas

Para evitar estar realizando accesos a la sede del catastro o a cualquier otra administración con nuestro certificado de usuario y que empiecen a sospechar de nosotros, lo mejor es que nos montemos un entorno de pruebas para ver cómo funciona nuestro certificado.

Preparación de la máquina

Crear un servicio web con ssl y que acepte certificados de usuario va a requerir un poco de trabajo por nuestra parte. Lo primero que debemos hacer, si no lo hemos hecho ya, es activar el Internet Information Server de nuestra máquina (la otra opción era usar el IIS Express, pero para utilizar los certificados de usuario es más complicado que usar el IIS directamente).

Para activarlo buscamos en el panel de control la activación de características de Windows:

image

Y activamos Internet Information Services. Es importante activar también las opciones de ASP.NET dentro del IIS para poder ejecutar y depurar el código que vamos a crear desde el Visual Studio:

image

Ahora que tenemos las herramientas y el IIS instalado, vamos a configurar el IIS para que acepte los certificados.

Vamos a necesitar una carpeta donde alojar nuestro sitio ssl. Normalmente encontraremos en c:\inetpub todo el contenido del IIS, dentro de esa carpeta podemos crear una nueva llamada sslroot:

image

Dentro de esta carpeta activaremos un sitio del IIS, para crearlo abrimos el InetMgr.exe

image

Antes de crear el sitio necesitaremos crear un certificado de pruebas para nuestro servidor, pulsamos en Server Certificates:

image

En las acciones podemos crear un certificado auto-firmado para nuestra máquina local:

image

Le damos un nombre que podamos recordar:

image

Creación de sitio web con ssl

Ahora que ya tenemos una carpeta y el certificado, podemos crear un nuevo sitio web que los utilicen:

image

Y configuramos el sitio como un sitio https:

image

  • Le damos un nombre: pruebassl
  • Una carpeta: c\inetpub\sslroot
  • Seleccionamos el enlace como https
  • Asignamos el certificado que acabamos de crear: pruebassl

En el nuevo sitio que hemos creado, encontraremos la opción SSL Settings:

image

Pulsamos sobre ella y configuramos el sitio para que acepte certificados de usuario:

image

Una vez cambiado, hay que pulsar sobre el botón aplicar que tenemos en la barra de acciones:

image

Ahora, en el caso de que tengamos un certificado de usuario instalado, nos solicitará el certificado de entre los posibles candidatos:

image

Pero al entrar con cualquiera de los certificados que tengamos nos encontraremos con el siguiente mensaje, explicándonos que el certificado no es confiable:

image

Solución de errores de certificado

Esto ocurre porque no hemos activado el certificado raíz de la FNMT para que acepte certificados de cliente, pues habitualmente se usa sólo para autentificar los servidores de la propia FNMT.

Para activarlo abrimos la MMC de certificados de la máquina:

image

Vamos a la carpeta donde están las autoridades certificadoras de raíz:

image

Y dentro de los certificados deberíamos encontrar el certificado de CA de la FNMT (si no lo tenemos instalado no nos funcionará nuestro certificado personal):

image

Realizamos doble-click sobre él y en la pestaña detalles vamos a editar propiedades:

image

En las propiedades editamos la autentificación de cliente:

image

Ahora ya podemos volver a abrir el sitio (https://localhost) y nos encontraremos con otro problema, nuestro certificado de cliente ha sido revocado:

image

Esto ocurre porque no estamos pagando a la FNMT para que nos proporcione la lista de revocación de certificados. Como lo estamos haciendo en un servidor de pruebas, podemos configurar el sitio para que no verifique la lista de revocación de certificados. Vamos a tener que tirar de línea de comandos para ejecutar el comando netsh. Abrimos un cmd en modo administrador y ejecutamos el siguiente comando:

C:\Windows\system32>netsh http show sslcert ipport=0.0.0.0:443

Nos mostrará un resultado parecido a este, con la información de nuestro certificado:

SSL Certificate bindings:

-------------------------

IP:port : 0.0.0.0:443

Certificate Hash : 0afbd1190936cd99b3ada40f8faca580e467712d

Application ID : {4dc3e181-e14b-4a21-b022-59fc669b0914}

Certificate Store Name : My

Verify Client Certificate Revocation : Enabled

Verify Revocation Using Cached Client Certificate Only : Disabled

Usage Check : Enabled

Revocation Freshness Time : 0

URL Retrieval Timeout : 0

Ctl Identifier : (null)

Ctl Store Name : (null)

DS Mapper Usage : Disabled

Negotiate Client Certificate : Disabled

Nos proporcionará la información del certificado que tenemos instalado para nuestro servicio ssl. Como podemos ver la opción “Verify Client Certificate Revocation” está activada. Para desactivarla tenemos que borrar la configuración y volver a añadirlo. Nos copiamos los datos que nos ha proporcionado el comando, pues los necesitaremos para volver a configurar el servicio y borramos el certificado:

C:\Windows\system32>netsh http delete sslcert ipport=0.0.0.0:443

Finalmente, utilizando la información del Hash y del appid que teníamos en la ejecución anterior, volvemos a añadir el certificado con la opción verifyclientcertrevocation con el valor disable:

C:\Windows\system32>netsh http add sslcert ipport=0.0.0.0:443 certhash=0afbd1190

936cd99b3ada40f8faca580e467712d appid={4dc3e181-e14b-4a21-b022-59fc669b0914} cer

tstorename=My verifyclientcertrevocation=disable

 

Página de lectura del certificado

Ahora nos falta escribir un poco de código para leer el certificado y mostrar por pantalla el contenido para comprobar que lo estamos recibiendo correctamente. Utilizaremos Visual Studio Express y crearemos una página web sencilla para mostrarlos.

Ejecutamos el Visual Studio Express 2012 for Web en modo administrador y abrimos un sitio web existente:

image

Si hemos ejecutado el VS en modo administrador nos debería aparecer el sitio de IIS que hemos creado en la lista de IIS Sites:

image

Creamos dentro del sitio una nueva WebPage y la llamamos Default:

image

Sustituimos el código de la plantilla por el siguiente:

  1: <!DOCTYPE html>
  2: <html>
  3:     <head>
  4:         <title></title>
  5:     </head>
  6:     <body>
  7:         <table>
  8:         @foreach (string key in Request.ClientCertificate.AllKeys)
  9:         {
  10:             <tr>
  11:                 <td>@key</td><td>
  12:             @if (key == "PUBLICKEY" || key == "CERTIFICATE")
  13:             {
  14:                 @: [[[Datos binarios]]]
  15:             }
  16:             else
  17:             {
  18:                 @Request.ClientCertificate[key]
  19:             }
  20:                     </td>
  21:             </tr>
  22:         }
  23:         </table>
  24:     </body>
  25: </html>

El código nos genera una tabla con la lista plana de todas las propiedades del certificado digital. Dentro de la petición http viene el certificado de cliente. En el código nos saltamos la clave pública y el certificado pues están codificados y mostrarían muchos caracteres sin sentido. Al ejecutarlo podremos ver el contenido del certificado.

Sólo nos queda eliminar un error que nos impediría utilizar el servicio desde una aplicación de Windows 8. Cada vez que abrimos la aplicación web nos mostrará un error de certificado:

image

En este caso ocurre porque estamos accediendo al servidor como https://localhost pero el certificado ha sido emitido para la máquina local con su nombre de dominio. Podemos abrir el certificado para comprobarlo desde la barra del IE10, una vez hemos abierto la página:

image

Al abrir el certificado, veremos que está emitido para mi máquina con un nombre diferente de localhost.

image

 

Entonces, bastará con acceder a al servicio con el nombre de la máquina local (o del dominio) en lugar de localhost para que no me aparezca el error de certificado.

La aplicación de Windows 8

Ya hemos creado nuestro servicio y teníamos una aplicación que accedía al catastro. Para poder hacer pruebas, la cambiamos un poco para que acceda a nuestro servicio:

  1: new WinJS.xhr({
  2:     url: "https://mimaquina.midominio.local/"
  3: }).then(function (e) {
  4:     contenido.innerHTML = e.responseText;
  5: },
  6: function (ex) {
  7:     contenido.innerHTML=toStaticHTML(ex.response);
  8: });

Y al acceder nos solicitará qué certificado queremos usar, pues en nuestro servicio no hemos restringido los certificados que acepta:

image

Una vez seleccionemos el certificado de la FNMT y aceptemos su uso, recibiremos el contenido en nuestra aplicación:

image

Resumen

Usar certificados de usuario en las aplicaciones Windows 8 es muy sencillo pues el sistema operativo se encarga de utilizar el certificado adecuado en cada situación. En este artículo también hemos introducido la gestión de los certificados desde un servicio web de pruebas en nuestra máquina local.

Son sólo los primeros pasos, pues con los certificados de usuario podemos realizar muchas cosas más: en servidor podemos mapear los certificados hacia nuestro sistema de autentificación, en cliente podemos descargar certificados del servidor tras realizar la autentificación y guardarlos en el almacén local de la aplicación y algunas cosas más que dejaré para otro artículo.

Referencias y enlaces interesantes