Compartir a través de


Windows Hello

En este artículo se describe la tecnología windows Hello que se incluye como parte de Windows y se describe cómo los desarrolladores pueden implementar esta tecnología para proteger sus aplicaciones de Windows y los servicios back-end. Resalta las funcionalidades específicas de estas tecnologías que ayudan a mitigar las amenazas que surgen del uso de credenciales convencionales y proporciona instrucciones sobre el diseño e implementación de estas tecnologías como parte de un lanzamiento de cliente de Windows.

Nota:

Este artículo se centra en el desarrollo de aplicaciones. Para obtener información sobre la arquitectura y los detalles de implementación de Windows Hello, consulte Planear una implementación de Windows Hello para empresas.

Para ver un tutorial paso a paso sobre cómo crear una aplicación WinUI con Windows Hello y el servicio de autenticación de respaldo, consulte los artículos aplicación de inicio de sesión de Windows Hello y servicio de inicio de sesión de Windows Hello.

Introducción

Una suposición fundamental sobre la seguridad de la información es que un sistema puede identificar quién lo está usando. La identificación de un usuario permite al sistema decidir si el usuario se identifica correctamente (un proceso conocido como autenticación) y, a continuación, decidir qué debe hacer un usuario autenticado correctamente (autorización). La mayoría de los sistemas informáticos implementados en todo el mundo dependen de las credenciales de usuario para tomar decisiones de autenticación y autorización, lo que significa que estos sistemas dependen de contraseñas reutilizables creadas por el usuario como base para su seguridad. La máxima citada que la autenticación puede implicar "algo que sabe, algo que tiene o algo que esté" resalta perfectamente el problema: una contraseña reutilizable es un factor de autenticación por sí mismo, por lo que cualquier persona que conoce la contraseña puede suplantar al usuario que lo posee.

Problemas con las credenciales tradicionales

Desde mediados de la década de 1960, cuando Fernando Corbató y su equipo en el Instituto de Tecnología de Massachusetts defendieron la introducción de la contraseña, los usuarios y los administradores han tenido que tratar con el uso de contraseñas para la autenticación y autorización de usuarios. Con el tiempo, el estado del arte para el almacenamiento de contraseñas y el uso ha avanzado un poco (con hash seguro y saling, por ejemplo), pero todavía nos encontramos con dos problemas. Las contraseñas son fáciles de clonar y son fáciles de robar. Además, los errores de implementación pueden representarlos inseguros y los usuarios tienen un tiempo difícil de equilibrar la comodidad y la seguridad.

Robo de credenciales

El mayor riesgo de las contraseñas es sencillo: un atacante puede robarlas con facilidad. Todos los lugares donde se escriba, procese o almacene una contraseña son vulnerables. Por ejemplo, un atacante puede robar una colección de contraseñas o hashes de un servidor de autenticación mediante la interceptación del tráfico de red a un servidor de aplicaciones, mediante la implementación de malware en una aplicación o en un dispositivo, mediante el registro de pulsaciones de teclas de usuario en un dispositivo o viendo qué caracteres escribe un usuario. Estos son solo los métodos de ataque más comunes.

Otro riesgo relacionado es el de la reproducción de credenciales, en la que un atacante captura una credencial válida al interceptar en una red no segura y, a continuación, la reproduce más adelante para suplantar a un usuario válido. La mayoría de los protocolos de autenticación (incluidos Kerberos y OAuth) protegen contra ataques de reproducción mediante la inclusión de una marca de tiempo en el proceso de intercambio de credenciales, pero esa táctica solo protege el token que emite el sistema de autenticación, no la contraseña que proporciona el usuario para obtener el vale en primer lugar.

Reutilización de credenciales

El enfoque común de usar una dirección de correo electrónico como el nombre de usuario empeora el problema. Un atacante que recupera correctamente un par de nombre de usuario y contraseña de un sistema en peligro puede probar ese mismo par en otros sistemas. Esta táctica funciona sorprendentemente a menudo para permitir que los atacantes entren en un sistema en peligro en otros sistemas. El uso de direcciones de correo electrónico como nombres de usuario conduce a problemas adicionales que exploraremos más adelante en esta guía.

Solución de problemas de credenciales

Solucionar los problemas que plantea la contraseña es complicado. La restricción de las directivas de contraseñas por sí solas no lo hará; los usuarios pueden simplemente reciclar, compartir o escribir contraseñas. Aunque la educación del usuario es fundamental para la seguridad de la autenticación, el ámbito educativo no elimina el problema tampoco.

Windows Hello reemplaza las contraseñas por autenticación fuerte en dos fases (2FA) comprobando las credenciales existentes y creando una credencial específica del dispositivo que protege un gesto de usuario biométrico o basado en PIN.

¿Qué es Windows Hello?

Windows Hello es el nombre que Microsoft ha dado al nuevo sistema de inicio de sesión biométrico integrado en Windows. Al estar integrado directamente en el sistema operativo, Windows Hello permite la identificación facial o dactilar para desbloquear los dispositivos de los usuarios. La autenticación se produce cuando el usuario proporciona su identificador biométrico único para acceder a las credenciales específicas del dispositivo, lo que significa que un atacante que roba el dispositivo no puede iniciar sesión en él a menos que ese atacante tenga el PIN. El almacén seguro de credenciales de Windows protege los datos biométricos del dispositivo. Con Windows Hello para desbloquear un dispositivo, el usuario autorizado obtiene acceso a toda su experiencia, aplicaciones, datos, sitios web y servicios de Windows.

El autenticador de Windows Hello se conoce como Hello. Hello es único para la combinación de un dispositivo individual y un usuario específico. No se mueve entre dispositivos, no se comparte con un servidor o una aplicación de llamada y no se puede extraer fácilmente de un dispositivo. Si varios usuarios comparten un dispositivo, cada usuario debe configurar su propia cuenta. Cada cuenta obtiene un hello único para ese dispositivo. Puede pensar en un hello como token que puede usar para desbloquear (o liberar) una credencial almacenada. El propio Hello no le autentica en una aplicación o servicio, pero libera las credenciales que pueden. En otras palabras, Hello no es una credencial de usuario, pero es un segundo factor para el proceso de autenticación.

Autenticación de Windows Hello

Windows Hello proporciona una forma sólida para que un dispositivo reconozca a un usuario individual, lo que aborda la primera parte de la ruta entre un usuario y un servicio o elemento de datos solicitado. Una vez que el dispositivo ha reconocido al usuario, aún debe autenticarlo antes de determinar si le concede acceso a un recurso solicitado. Windows Hello proporciona una 2FA segura que está totalmente integrada en Windows y reemplaza las contraseñas reutilizables por la combinación de un dispositivo específico y un gesto biométrico o PIN.

Windows Hello no es solo un reemplazo de los sistemas 2FA tradicionales, sin embargo. Conceptualmente es similar a las tarjetas inteligentes: la autenticación se realiza mediante primitivos criptográficos en lugar de comparaciones de cadenas, y el material clave del usuario es seguro dentro del hardware resistente a manipulaciones. Windows Hello no requiere los componentes de infraestructura adicionales necesarios para la implementación de tarjetas inteligentes, tampoco. En concreto, no necesita una infraestructura de clave pública (PKI) para administrar certificados, si actualmente no tiene una. Windows Hello combina las principales ventajas de las tarjetas inteligentes (flexibilidad de implementación para las tarjetas inteligentes virtuales y seguridad sólida para las tarjetas inteligentes físicas) sin ninguno de sus inconvenientes.

Funcionamiento de Windows Hello

Cuando el usuario configura Windows Hello en su máquina, genera un nuevo par de claves pública y privada en el dispositivo. El módulo de plataforma segura (TPM) genera y protege esta clave privada. Si el dispositivo no tiene un chip TPM, la clave privada se cifra y protege mediante software. Además, los dispositivos habilitados para TPM generan un bloque de datos que se puede usar para atestiguar que una clave está enlazada a TPM. Esta información de atestación se puede usar en la solución para decidir si se concede al usuario un nivel de autorización diferente, por ejemplo.

Para habilitar Windows Hello en un dispositivo, el usuario debe tener su cuenta de Id. de Microsoft Entra o cuenta Microsoft conectada en la configuración de Windows.

Protección de las claves

Cada vez que se genera material clave, debe protegerse contra ataques. La forma más sólida de hacerlo es a través de hardware especializado. Hay un largo historial de uso de módulos de seguridad de hardware (HSM) para generar, almacenar y procesar claves para aplicaciones críticas para la seguridad. Las tarjetas inteligentes son un tipo especial de HSM, ya que son dispositivos compatibles con el estándar TPM del grupo de computación de confianza. Siempre que sea posible, la implementación de Windows Hello aprovecha el hardware de TPM incorporado para generar, almacenar y procesar claves. Sin embargo, Windows Hello y Windows Hello for Work no requieren un TPM incorporado.

Siempre que sea factible, Microsoft recomienda el uso del hardware de TPM. El TPM protege contra una variedad de ataques conocidos y potenciales, incluidos los ataques por fuerza bruta de PIN. El TPM también proporciona una capa adicional de protección después de un bloqueo de cuenta. Cuando el TPM ha bloqueado el material de clave, el usuario debe restablecer el PIN. Restablecer el PIN significa que se quitarán todas las claves y certificados cifrados con el material de clave anterior.

Autenticación

Cuando un usuario quiere acceder al material de clave protegido, el proceso de autenticación comienza con el usuario escribiendo un PIN o un gesto biométrico para desbloquear el dispositivo, un proceso que a veces se denomina "liberar la clave".

Una aplicación nunca puede usar las claves de otra aplicación, ni puede alguien usar nunca las claves de otro usuario. Estas claves se usan para firmar solicitudes que se envían al proveedor de identidades o al IDP, buscando acceso a los recursos especificados. Las aplicaciones pueden usar API específicas para solicitar operaciones que requieran material clave para acciones concretas. El acceso a través de estas API requiere una validación explícita a través de un gesto de usuario y el material de clave no se expone a la aplicación solicitante. En su lugar, la aplicación solicita una acción específica, como firmar un fragmento de datos, y la capa de Windows Hello controla el trabajo real y devuelve los resultados.

Preparación para implementar Windows Hello

Ahora que tenemos un conocimiento básico de cómo funciona Windows Hello, echemos un vistazo a cómo implementarlos en nuestras propias aplicaciones.

Hay diferentes escenarios que se pueden implementar con Windows Hello. Por ejemplo, simplemente inicia sesión en la aplicación en un dispositivo. El otro escenario común sería autenticarse en un servicio. En lugar de usar un nombre de inicio de sesión y una contraseña, usará Windows Hello. En las secciones siguientes, analizaremos la implementación de un par de escenarios diferentes, incluido cómo autenticarse en los servicios con Windows Hello y cómo convertir de un sistema existente de nombre de usuario y contraseña a un sistema windows Hello.

Implementación de Windows Hello

En esta sección, comenzaremos con un escenario de campo verde sin ningún sistema de autenticación existente y se explica cómo implementar Windows Hello.

En la sección siguiente se explica cómo migrar desde un sistema existente de nombre de usuario y contraseña. Sin embargo, incluso si esa sección le interesa más, es posible que desee examinar esta para obtener una comprensión básica del proceso y el código necesario.

Inscripción de nuevos usuarios

Comenzamos con un nuevo servicio que usará Windows Hello y un nuevo usuario hipotético que está listo para registrarse en un nuevo dispositivo.

El primer paso es comprobar que el usuario puede usar Windows Hello. La aplicación comprueba la configuración del usuario y las funcionalidades de la máquina para asegurarse de que puede crear claves de identificador de usuario. Si la aplicación determina que el usuario aún no ha habilitado Windows Hello, solicita al usuario que lo configure antes de usar la aplicación.

Para habilitar Windows Hello, el usuario solo tiene que configurar un PIN en la configuración de Windows, a menos que el usuario lo configure durante la experiencia rápida (OOBE).

Las siguientes líneas de código muestran una manera sencilla de comprobar si el usuario está configurado para Windows Hello.

var keyCredentialAvailable = await KeyCredentialManager.IsSupportedAsync();
if (!keyCredentialAvailable)
{
    // User didn't set up PIN yet
    return;
}

El siguiente paso es pedir al usuario información para registrarse con el servicio. Puede optar por pedir al usuario el nombre, el apellido, la dirección de correo electrónico y un nombre de usuario único. Puede usar la dirección de correo electrónico como identificador único; es para ti.

En este escenario, usamos la dirección de correo electrónico como identificador único para el usuario. Una vez que el usuario se suscribe, debe considerar la posibilidad de enviar un correo electrónico de validación para asegurarse de que la dirección es válida. Esto le proporciona un mecanismo para restablecer la cuenta si es necesario.

Si el usuario ha configurado su PIN, la aplicación crea keyCredential del usuario. La aplicación también obtiene la información de atestación de clave opcional para adquirir la prueba criptográfica de que la clave se genera en el TPM. La clave pública generada y, opcionalmente, la atestación, se envía al servidor back-end para registrar el dispositivo que se está usando. Cada par de claves generado en cada dispositivo será único.

El código para crear keyCredential tiene este aspecto:

var keyCreationResult = await KeyCredentialManager.RequestCreateAsync(
    AccountId, KeyCredentialCreationOption.ReplaceExisting);

RequestCreateAsync es la llamada que crea la clave pública y privada. Si el dispositivo tiene el chip TPM correcto, las API solicitarán el chip TPM para crear la clave pública y privada y almacenar el resultado; si no hay ningún chip TPM disponible, el sistema operativo creará el par de claves en el código. No hay forma de que la aplicación acceda directamente a las claves privadas creadas. Parte de la creación de los pares de claves también es la información de atestación resultante. (Consulte la sección siguiente para obtener más información sobre la atestación).

Después de crear el par de claves y la información de atestación en el dispositivo, la clave pública, la información de atestación opcional y el identificador único (como la dirección de correo electrónico) deben enviarse al servicio de registro de back-end y almacenarse en el back-end.

Para permitir que el usuario acceda a la aplicación en varios dispositivos, el servicio back-end debe poder almacenar varias claves para el mismo usuario. Dado que cada clave es única para cada dispositivo, almacenaremos todas estas claves conectadas al mismo usuario. Se usa un identificador de dispositivo para ayudar a optimizar la parte del servidor al autenticar a los usuarios. Hablamos de esto con más detalle en la sección siguiente.

Un esquema de base de datos de ejemplo para almacenar esta información en el back-end podría tener este aspecto:

Esquema de base de datos de ejemplo de Windows Hello

La lógica de registro podría tener este aspecto:

Lógica de registro de Windows Hello

Por supuesto, la información de registro que recopile puede incluir mucha más información de identificación de la que se incluye en este escenario simple. Por ejemplo, si la aplicación accede a un servicio protegido como uno para la banca, tendría que solicitar una prueba de identidad y otras cosas como parte del proceso de registro. Una vez que se cumplen todas las condiciones, la clave pública de este usuario se almacenará en el back-end y se usará para validar la próxima vez que el usuario use el servicio.

using System;
using System.Runtime;
using System.Threading.Tasks;
using Windows.Storage.Streams;
using Windows.Security.Credentials;

static async void RegisterUser(string AccountId)
{
    var keyCredentialAvailable = await KeyCredentialManager.IsSupportedAsync();
    if (!keyCredentialAvailable)
    {
        // The user didn't set up a PIN yet
        return;
    }

    var keyCreationResult = await KeyCredentialManager.RequestCreateAsync(AccountId, KeyCredentialCreationOption.ReplaceExisting);
    if (keyCreationResult.Status == KeyCredentialStatus.Success)
    {
        var userKey = keyCreationResult.Credential;
        var publicKey = userKey.RetrievePublicKey();
        var keyAttestationResult = await userKey.GetAttestationAsync();
        IBuffer keyAttestation = null;
        IBuffer certificateChain = null;
        bool keyAttestationIncluded = false;
        bool keyAttestationCanBeRetrievedLater = false;

        keyAttestationResult = await userKey.GetAttestationAsync();
        KeyCredentialAttestationStatus keyAttestationRetryType = 0;

        switch (keyAttestationResult.Status)
        {
            case KeyCredentialAttestationStatus.Success:
                keyAttestationIncluded = true;
                keyAttestation = keyAttestationResult.AttestationBuffer;
                certificateChain = keyAttestationResult.CertificateChainBuffer;
                break;
            case KeyCredentialAttestationStatus.TemporaryFailure:
                keyAttestationRetryType = KeyCredentialAttestationStatus.TemporaryFailure;
                keyAttestationCanBeRetrievedLater = true;
                break;
            case KeyCredentialAttestationStatus.NotSupported:
                keyAttestationRetryType = KeyCredentialAttestationStatus.NotSupported;
                keyAttestationCanBeRetrievedLater = true;
                break;
        }
    }
    else if (keyCreationResult.Status == KeyCredentialStatus.UserCanceled ||
        keyCreationResult.Status == KeyCredentialStatus.UserPrefersPassword)
    {
        // Show error message to the user to get confirmation that user
        // does not want to enroll.
    }
}

Atestación

Al crear el par de claves, también hay una opción para solicitar la información de atestación, que se genera mediante el chip de TPM. Esta información opcional se puede enviar al servidor como parte del proceso de registro. La atestación de claves de TPM es un protocolo que demuestra criptográficamente que una clave está enlazada a TPM. Este tipo de atestación se puede usar para garantizar que se produjo una determinada operación criptográfica en el TPM de un equipo determinado.

Cuando recibe la clave RSA generada, la instrucción de atestación y el certificado AIK, el servidor comprueba las condiciones siguientes:

  • La firma del certificado AIK es válida.
  • El certificado AIK se encadena a una raíz de confianza.
  • El certificado AIK y su cadena están habilitados para el OID de EKU "2.23.133.8.3" (el nombre descriptivo es "Certificado de clave de identidad de atestación").
  • El certificado AIK es el tiempo válido.
  • Todos los certificados de ENTIDAD de certificación emisoras en la cadena son válidos en el tiempo y no se revocan.
  • La instrucción de atestación se forma correctamente.
  • La firma del blob KeyAttestation usa una clave pública AIK.
  • La clave pública incluida en el blob KeyAttestation coincide con la clave RSA pública que el cliente envió junto con la instrucción de atestación.

La aplicación puede asignar al usuario un nivel de autorización diferente, en función de estas condiciones. Por ejemplo, si se produce un error en una de estas comprobaciones, podría no inscribir al usuario o limitar lo que el usuario puede hacer.

Inicio de sesión con Windows Hello

Una vez inscrito el usuario en el sistema, puede usar la aplicación. En función del escenario, puede pedir a los usuarios que se autentiquen antes de que puedan empezar a usar la aplicación o simplemente pedirles que se autentiquen una vez que empiecen a usar los servicios back-end.

Forzar al usuario a iniciar sesión de nuevo

En algunos escenarios, es posible que quieras que el usuario demuestre que es la persona que ha iniciado sesión actualmente, antes de acceder a la aplicación o a veces antes de realizar una determinada acción dentro de la aplicación. Por ejemplo, antes de que una aplicación bancaria envíe el comando transfer money al servidor, quiere asegurarse de que es el usuario, en lugar de alguien que encontró un dispositivo que ha iniciado sesión, intentando realizar una transacción. Puedes forzar al usuario a iniciar sesión de nuevo en la aplicación mediante la clase UserConsentVerifier . La siguiente línea de código obligará al usuario a escribir sus credenciales.

La siguiente línea de código obligará al usuario a escribir sus credenciales.

UserConsentVerificationResult consentResult = await UserConsentVerifier.RequestVerificationAsync("userMessage");
if (consentResult.Equals(UserConsentVerificationResult.Verified))
{
    // continue
}

También puede usar el mecanismo de respuesta de desafío del servidor, que requiere que un usuario escriba su código PIN o sus credenciales biométricas. Depende del escenario que usted como desarrollador necesite implementar. Este mecanismo se describe en la sección siguiente.

Autenticación en el back-end

Cuando la aplicación intenta acceder a un servicio back-end protegido, el servicio envía un desafío a la aplicación. La aplicación usa la clave privada del usuario para firmar el desafío y devolverla al servidor. Dado que el servidor ha almacenado la clave pública para ese usuario, usa las API criptográficas estándar para asegurarse de que el mensaje se firmó realmente con la clave privada correcta. En el cliente, la firma se realiza mediante las API de Windows Hello; el desarrollador nunca tendrá acceso a la clave privada de ningún usuario.

Además de comprobar las claves, el servicio también puede comprobar la atestación de claves y distinguir si hay alguna limitación invocada sobre cómo se almacenan las claves en el dispositivo. Por ejemplo, cuando el dispositivo usa TPM para proteger las claves, es más seguro que los dispositivos que almacenan las claves sin TPM. La lógica de back-end podría decidir, por ejemplo, que el usuario solo puede transferir una determinada cantidad de dinero cuando no se usa ningún TPM para reducir los riesgos.

La atestación solo está disponible para dispositivos con un chip TPM versión 2.0 o posterior. Por lo tanto, debe tener en cuenta que es posible que esta información no esté disponible en todos los dispositivos.

El flujo de trabajo de cliente podría tener un aspecto similar al siguiente gráfico:

Flujo de trabajo de cliente de Windows Hello

Cuando la aplicación llama al servicio en el back-end, el servidor envía un desafío. El desafío se firma con el código siguiente:

var openKeyResult = await KeyCredentialManager.OpenAsync(AccountId);

if (openKeyResult.Status == KeyCredentialStatus.Success)
{
    var userKey = openKeyResult.Credential;
    var publicKey = userKey.RetrievePublicKey();
    var signResult = await userKey.RequestSignAsync(message);

    if (signResult.Status == KeyCredentialStatus.Success)
    {
        return signResult.Result;
    }
    else if (signResult.Status == KeyCredentialStatus.UserPrefersPassword)
    {

    }
}

La primera línea, KeyCredentialManager.OpenAsync, pedirá a Windows que abra el identificador de clave. Si se ejecuta correctamente, puedes firmar el mensaje de desafío con el método KeyCredential.RequestSignAsync , lo que hace que Windows solicite el PIN del usuario o la biometría a través de Windows Hello. En ningún momento el desarrollador tendrá acceso a la clave privada del usuario. Esto se mantiene seguro a través de las API.

Las API solicitan a Windows que firmen el desafío con la clave privada. A continuación, el sistema solicita al usuario un código PIN o un inicio de sesión biométrico configurado. Cuando se introduce la información correcta, el sistema puede pedir al chip TPM que realice las funciones criptográficas y firme el desafío. (O use la solución de software de reserva, si no hay ningún TPM disponible). El cliente debe devolver el desafío firmado al servidor.

En este diagrama de secuencia se muestra un flujo de desafío y respuesta básico:

Respuesta de desafío de Windows Hello

A continuación, el servidor debe validar la firma. Cuando se solicita la clave pública y se envía al servidor para su uso para la validación futura, se encuentra en un blob publicKeyInfo codificado en ASN.1. Si examina el ejemplo de código de Windows Hello en GitHub, verá que hay clases auxiliares para encapsular las funciones de Crypt32 para traducir el blob codificado asn.1 a un blob CNG, que se usa con más frecuencia. El blob contiene el algoritmo de clave pública, que es RSA y la clave pública RSA.

En el ejemplo, la razón por la que se convierte el blob codificado asN.1 en un blob CNG es para que se pueda usar con CNG y la API BCrypt. Si busca el blob CNG, le indicará la estructura de BCRYPT_KEY_BLOB relacionada. Esta superficie de API se puede usar para la autenticación y el cifrado en aplicaciones de Windows. ASN.1 es un estándar documentado para comunicar estructuras de datos que se pueden serializar y que se suelen usar en criptografía de clave pública y con certificados. Por eso se devuelve la información de clave pública de esta manera. La clave pública es una clave RSA; y ese es el algoritmo que Usa Windows Hello cuando firma los datos.

Una vez que tenga el blob CNG, debe validar el desafío firmado con la clave pública del usuario. Puesto que todos usan su propio sistema o tecnología de back-end, no hay ninguna manera genérica de implementar esta lógica. Usamos SHA256 como algoritmo hash y Pkcs1 para SignaturePadding, así que asegúrese de que es lo que usa al validar la respuesta firmada del cliente. De nuevo, consulte el ejemplo para obtener una manera de hacerlo en el servidor en .NET 4.6, pero en general tendrá un aspecto similar al siguiente:

using (RSACng pubKey = new RSACng(publicKey))
{
    retval = pubKey.VerifyData(originalChallenge, responseSignature, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
}

Leemos la clave pública almacenada, que es una clave RSA. Validamos el mensaje de desafío firmado con la clave pública y, si se desprotece, autorizamos al usuario. Si el usuario está autenticado, la aplicación puede llamar a los servicios back-end como normal.

El código completo podría tener un aspecto similar al siguiente:

using System;
using System.Runtime;
using System.Threading.Tasks;
using Windows.Storage.Streams;
using Windows.Security.Cryptography;
using Windows.Security.Cryptography.Core;
using Windows.Security.Credentials;

static async Task<IBuffer> GetAuthenticationMessageAsync(IBuffer message, String AccountId)
{
    var openKeyResult = await KeyCredentialManager.OpenAsync(AccountId);

    if (openKeyResult.Status == KeyCredentialStatus.Success)
    {
        var userKey = openKeyResult.Credential;
        var publicKey = userKey.RetrievePublicKey();
        var signResult = await userKey.RequestSignAsync(message);
        if (signResult.Status == KeyCredentialStatus.Success)
        {
            return signResult.Result;
        }
        else if (signResult.Status == KeyCredentialStatus.UserCanceled)
        {
            // Launch app-specific flow to handle the scenario 
            return null;
        }
    }
    else if (openKeyResult.Status == KeyCredentialStatus.NotFound)
    {
        // PIN reset has occurred somewhere else and key is lost.
        // Repeat key registration
        return null;
    }
    else
    {
        // Show custom UI because unknown error has happened.
        return null;
    }
}

La implementación del mecanismo de desafío y respuesta correcto está fuera del ámbito de este documento, pero este tema es algo que requiere atención para crear correctamente un mecanismo seguro para evitar elementos como ataques de reproducción o ataques de tipo "man in the middle".

Inscripción de otro dispositivo

Es habitual que los usuarios tengan varios dispositivos con las mismas aplicaciones instaladas hoy en día. ¿Cómo funciona esto al usar Windows Hello con varios dispositivos?

Al usar Windows Hello, cada dispositivo creará un conjunto de claves pública y privada único. Esto significa que si quiere que un usuario pueda usar varios dispositivos, el back-end debe poder almacenar varias claves públicas de este usuario. Consulte el diagrama de base de datos de la sección Inscripción de nuevos usuarios para obtener un ejemplo de la estructura de la tabla.

El registro de otro dispositivo es casi el mismo que el registro de un usuario por primera vez. Todavía tiene que asegurarse de que el usuario que se registra para este nuevo dispositivo es realmente el usuario que reclama ser. Puede hacerlo con cualquier mecanismo de autenticación en dos fases que se use hoy en día. Hay varias maneras de lograrlo de forma segura. Todo depende de su escenario.

Por ejemplo, si sigue usando el nombre de inicio de sesión y la contraseña, puede usarlo para autenticar al usuario y pedirle que use uno de sus métodos de verificación, como SMS o correo electrónico. Si no tiene un nombre de inicio de sesión y una contraseña, también puede usar uno de los dispositivos ya registrados y enviar una notificación a la aplicación en ese dispositivo. La aplicación autenticadora de MSA es un ejemplo de esto. En resumen, debe usar un mecanismo común de 2FA para registrar dispositivos adicionales para el usuario.

El código para registrar el nuevo dispositivo es exactamente el mismo que registrar al usuario por primera vez (desde dentro de la aplicación).

var keyCreationResult = await KeyCredentialManager.RequestCreateAsync(
    AccountId, KeyCredentialCreationOption.ReplaceExisting);

Para que sea más fácil que el usuario reconozca qué dispositivos están registrados, puede optar por enviar el nombre del dispositivo u otro identificador como parte del registro. Esto también es útil, por ejemplo, si desea implementar un servicio en el back-end donde los usuarios pueden anular el registro de dispositivos cuando se pierde un dispositivo.

Uso de varias cuentas en la aplicación

Además de admitir varios dispositivos para una sola cuenta, también es habitual admitir varias cuentas en una sola aplicación. Por ejemplo, quizás estés conectando a varias cuentas de Twitter desde la aplicación. Con Windows Hello, puedes crear varios pares de claves y admitir varias cuentas dentro de la aplicación.

Una manera de hacerlo es mantener el nombre de usuario o el identificador único descritos en la sección anterior sobre el almacenamiento aislado. Por lo tanto, cada vez que cree una nueva cuenta, almacene el identificador de cuenta en el almacenamiento aislado.

En la interfaz de usuario de la aplicación, permite al usuario elegir una de las cuentas creadas anteriormente o registrarse con una nueva. El flujo de creación de una nueva cuenta es el mismo que se ha descrito antes. Elegir una cuenta es cuestión de enumerar las cuentas almacenadas en la pantalla. Una vez que el usuario selecciona una cuenta, use el identificador de cuenta para iniciar sesión en el usuario de la aplicación:

var openKeyResult = await KeyCredentialManager.OpenAsync(AccountId);

El resto del flujo es el mismo que se ha descrito anteriormente. Para ser claros, todas estas cuentas están protegidas por el mismo PIN o gesto biométrico, ya que en este escenario se usan en un solo dispositivo con la misma cuenta de Windows.

Migración de un sistema existente a Windows Hello

En esta breve sección, abordaremos una aplicación empaquetada existente y un sistema back-end que usa una base de datos que almacena el nombre de usuario y la contraseña con hash. Estas aplicaciones recopilan credenciales del usuario cuando se inicia la aplicación y las usan cuando el sistema back-end devuelve el desafío de autenticación.

Aquí describiremos qué partes deben cambiarse o reemplazarse para que Windows Hello funcione.

Ya hemos descrito la mayoría de las técnicas de las secciones anteriores. Agregar Windows Hello al sistema existente implica agregar un par de flujos diferentes en la parte de registro y autenticación del código.

Un enfoque consiste en permitir que el usuario elija cuándo actualizar. Después de que el usuario inicie sesión en la aplicación y detecte que la aplicación y el sistema operativo son capaces de admitir Windows Hello, puede preguntar al usuario si quiere actualizar las credenciales para usar este sistema moderno y más seguro. Puedes usar el código siguiente para comprobar si el usuario es capaz de usar Windows Hello.

var keyCredentialAvailable = await KeyCredentialManager.IsSupportedAsync();

La interfaz de usuario podría tener un aspecto similar al siguiente:

Captura de pantalla de la interfaz de usuario de Windows Hello

Si el usuario decide empezar a usar Windows Hello, cree el elemento KeyCredential descrito antes. El servidor de registro de back-end agrega la clave pública y la instrucción de atestación opcional a la base de datos. Dado que el usuario ya está autenticado con el nombre de usuario y la contraseña, el servidor puede vincular las nuevas credenciales a la información de usuario actual de la base de datos. El modelo de base de datos podría ser el mismo que el ejemplo descrito anteriormente.

Si la aplicación pudo crear los usuarios KeyCredential, almacena el identificador de usuario en almacenamiento aislado para que el usuario pueda seleccionar esta cuenta de la lista una vez que se inicie la aplicación de nuevo. A partir de este punto, el flujo sigue exactamente los ejemplos descritos en las secciones anteriores.

El último paso para migrar a un escenario completo de Windows Hello es deshabilitar la opción de nombre de inicio de sesión y contraseña en la aplicación y quitar las contraseñas con hash almacenadas de la base de datos.

Resumen

Windows presenta un mayor nivel de seguridad que también es fácil de poner en práctica. Windows Hello proporciona un nuevo sistema de inicio de sesión biométrico que reconoce al usuario y derrota activamente los esfuerzos por eludir la identificación adecuada. A continuación, puede entregar varias capas de claves y certificados que nunca se pueden revelar o usar fuera del módulo de plataforma de confianza. Además, hay disponible un nivel de seguridad adicional mediante el uso opcional de claves de identidad de atestación y certificados.

Como desarrollador, puede usar esta guía sobre el diseño y la implementación de estas tecnologías para agregar fácilmente la autenticación segura a los lanzamientos empaquetados de aplicaciones de Windows para proteger las aplicaciones y los servicios back-end. El código necesario es mínimo y fácil de entender. Windows controla el trabajo pesado.

Las opciones de implementación flexibles permiten que Windows Hello reemplace o funcione junto con el sistema de autenticación existente. La experiencia de implementación es indoloro y económico. No se necesita ninguna infraestructura adicional para implementar la seguridad de Windows. Con Microsoft Hello integrado en el sistema operativo, Windows ofrece la solución más segura a los problemas de autenticación a los que se enfrenta el desarrollador moderno.

Misión cumplida. ¡Acabas de hacer que Internet sea un lugar más seguro!

Recursos adicionales

Artículos y código de ejemplo

Terminología

Término Definición
AIK Se usa una clave de identidad de atestación para proporcionar dicha prueba criptográfica (atestación de clave TPM) firmando las propiedades de la clave no migrable y proporcionando las propiedades y la firma al usuario de confianza para la comprobación. La firma resultante se denomina "instrucción de atestación". Dado que la firma se crea mediante la clave privada de AIK, que solo se puede usar en el TPM que lo creó, el usuario de confianza puede confiar en que la clave atestada es realmente no migrable y no se puede usar fuera de ese TPM.
Certificado AIK Un certificado AIK se usa para atestiguar la presencia de un AIK dentro de un TPM. También se usa para atestiguar que otras claves certificadas por el AIK se originaron en ese TPM concreto.
IDP Un IDP es un proveedor de identidades. Un ejemplo es la compilación de IDP de Microsoft para cuentas Microsoft. Cada vez que una aplicación necesita autenticarse con una MSA, puede llamar al IDP de MSA.
PKI La infraestructura de clave pública se usa normalmente para apuntar a un entorno hospedado por una propia organización y ser responsable de crear claves, revocar claves, etc.
TPM El módulo de plataforma de confianza se puede usar para crear pares de claves públicas y privadas criptográficas de forma que la clave privada nunca se pueda revelar o usar fuera del TPM (es decir, la clave no es migrable).
Atestación de clave de TPM Protocolo que demuestra criptográficamente que una clave está enlazada a TPM. Este tipo de atestación se puede usar para garantizar que se produjo una determinada operación criptográfica en el TPM de un equipo determinado.