Partilhar via


Windows Hello

Este artigo descreve a tecnologia Windows Hello que é fornecida como parte do Windows e discute como os desenvolvedores podem implementar essa tecnologia para proteger seus aplicativos e serviços de back-end do Windows. Ele destaca recursos específicos dessas tecnologias que ajudam a mitigar ameaças que surgem do uso de credenciais convencionais e fornece diretrizes sobre como projetar e implantar essas tecnologias como parte de uma distribuição de cliente Windows.

Observação

Este artigo se concentra no desenvolvimento de aplicativos. Para obter informações sobre a arquitetura e os detalhes de implementação do Windows Hello, consulte Planejar uma implantação do Windows Hello para Empresas.

Para obter um passo a passo sobre como criar um aplicativo WinUI usando Windows Hello e o serviço de autenticação de backup, consulte os artigos Aplicativo de logon do Windows Hello e Serviço de logon do Windows Hello.

Introdução

Uma suposição fundamental sobre segurança da informação é que um sistema pode identificar quem a está usando. A identificação de um usuário permite que o sistema decida se o usuário é identificado adequadamente (um processo conhecido como autenticação) e, em seguida, decida o que um usuário devidamente autenticado deve ser capaz de fazer (autorização). A esmagadora maioria dos sistemas de computador implantados em todo o mundo depende das credenciais do usuário para tomar decisões de autenticação e autorização, o que significa que esses sistemas dependem de senhas reutilizáveis criadas pelo usuário como base para sua segurança. A máxima frequentemente citada de que a autenticação pode envolver "algo que você sabe, algo que você tem ou algo que você é" destaca claramente o problema: uma senha reutilizável é um fator de autenticação por si só, então qualquer pessoa que conheça a senha pode se passar pelo usuário que a possui.

Problemas com credenciais tradicionais

Desde meados da década de 1960, quando Fernando Corbató e sua equipe do Instituto de Tecnologia de Massachusetts defenderam a introdução da senha, usuários e administradores tiveram que lidar com o uso de senhas para autenticação e autorização do usuário. Com o tempo, o estado da arte para armazenamento e uso de senhas avançou um pouco (com hashing seguro e salting, por exemplo), mas ainda nos deparamos com dois problemas. As senhas são fáceis de clonar e são fáceis de roubar. Além disso, as falhas de implementação podem torná-los inseguros e os usuários têm dificuldade em equilibrar conveniência e segurança.

Roubo de credenciais

O maior risco das senhas é simples: um invasor pode roubá-las com facilidade. Cada lugar em que uma senha é inserida, processada ou armazenada é vulnerável. Por exemplo, um invasor pode roubar uma coleção de senhas ou hashes de um servidor de autenticação espionando o tráfego de rede para um servidor de aplicativos, implantando malware em um aplicativo ou em um dispositivo, registrando as teclas digitadas pelo usuário em um dispositivo ou observando quais caracteres um usuário digita. Esses são apenas os métodos de ataque mais comuns.

Outro risco relacionado é o da repetição de credenciais, na qual um invasor captura uma credencial válida espionando uma rede insegura e, em seguida, a reproduz posteriormente para representar um usuário válido. A maioria dos protocolos de autenticação (incluindo Kerberos e OAuth) protege contra ataques de reprodução incluindo um carimbo de data/hora no processo de troca de credenciais, mas essa tática protege apenas o token que o sistema de autenticação emite, não a senha que o usuário fornece para obter o tíquete em primeiro lugar.

Reutilização de credenciais

A abordagem comum de usar um endereço de e-mail como nome de usuário piora um problema grave. Um invasor que recupera com sucesso um par de nome de usuário e senha de um sistema comprometido pode tentar o mesmo par em outros sistemas. Essa tática funciona com frequência surpreendente para permitir que os invasores saltem de um sistema comprometido para outros sistemas. O uso de endereços de e-mail como nomes de usuário leva a problemas adicionais que exploraremos mais adiante neste guia.

Resolvendo problemas de credenciais

Resolver os problemas que as senhas representam é complicado. Apertar as políticas de senha por si só não fará isso; Os usuários podem apenas reciclar, compartilhar ou anotar senhas. Embora a educação do usuário seja crítica para a segurança da autenticação, a educação por si só também não elimina o problema.

Windows Hello substitui senhas por autenticação de dois fatores (2FA) forte verificando as credenciais existentes e criando uma credencial específica do dispositivo que um gesto de usuário biométrico ou baseado em PIN protege.

O que é o Windows Hello?

Windows Hello é o nome que a Microsoft deu ao novo sistema de entrada biométrica integrado ao Windows. Por ser integrado diretamente ao sistema operacional, o Windows Hello permite a identificação facial ou por impressão digital para desbloquear os dispositivos dos usuários. A autenticação acontece quando o usuário fornece seu identificador biométrico exclusivo para acessar as credenciais específicas do dispositivo, o que significa que um invasor que rouba o dispositivo não pode fazer logon nele, a menos que esse invasor tenha o PIN. O armazenamento de credenciais seguras do Windows protege os dados biométricos no dispositivo. Ao usar o Windows Hello para desbloquear um dispositivo, o usuário autorizado obtém acesso a toda a sua experiência, aplicativos, dados, sites e serviços do Windows.

O autenticador do Windows Hello é conhecido como Hello. Um Hello é exclusivo para a combinação de um dispositivo individual e um usuário específico. Ele não faz roaming entre dispositivos, não é compartilhado com um servidor ou aplicativo de chamada e não pode ser facilmente extraído de um dispositivo. Se vários usuários compartilharem um dispositivo, cada usuário precisará configurar sua própria conta. Cada conta recebe um Hello exclusivo para esse dispositivo. Você pode pensar em um Hello como um token que pode ser usado para desbloquear (ou liberar) uma credencial armazenada. O Hello em si não autentica você em um aplicativo ou serviço, mas libera credenciais que podem. Em outras palavras, o Hello não é uma credencial de usuário, mas é um segundo fator para o processo de autenticação.

Autenticação do Windows Hello

O Windows Hello fornece uma maneira robusta para um dispositivo reconhecer um usuário individual, que aborda a primeira parte do caminho entre um usuário e um serviço ou item de dados solicitado. Depois que o dispositivo reconhece o usuário, ele ainda deve autenticá-lo antes de determinar se deseja conceder acesso a um recurso solicitado. O Windows Hello fornece 2FA forte que é totalmente integrada ao Windows e substitui senhas reutilizáveis pela combinação de um dispositivo específico e um gesto biométrico ou PIN.

No entanto, o Windows Hello não é apenas um substituto para os sistemas 2FA tradicionais. É conceitualmente semelhante aos cartões inteligentes: a autenticação é executada usando primitivos criptográficos em vez de comparações de cadeia de caracteres, e o material da chave do usuário é protegido dentro de hardware inviolável. O Windows Hello também não requer os componentes de infraestrutura extras necessários para a implantação de cartão inteligente. Em particular, você não precisa de uma PKI (Infraestrutura de Chave Pública) para gerenciar certificados, se não tiver uma no momento. O Windows Hello combina as principais vantagens dos cartões inteligentes: flexibilidade de implantação para cartões inteligentes virtuais e segurança robusta para cartões inteligentes físicos, sem nenhuma de suas desvantagens.

Como funciona o Windows Hello

Quando o usuário configura o Windows Hello em seu computador, ele gera um novo par de chaves pública-privada no dispositivo. O TPM (Trusted Platform Module ) gera e protege essa chave privada. Se o dispositivo não tiver um chip TPM, a chave privada será criptografada e protegida por software. Além disso, os dispositivos habilitados para TPM geram um bloco de dados que pode ser usado para atestar que uma chave está associada ao TPM. Essas informações de atestado podem ser usadas em sua solução para decidir se o usuário recebe um nível de autorização diferente, por exemplo.

Para habilitar o Windows Hello em um dispositivo, o usuário deve ter sua conta do Microsoft Entra ID ou a conta da Microsoft conectada nas configurações do Windows.

Como as chaves são protegidas

Sempre que o material de chave é gerado, ele deve ser protegido contra ataques. A maneira mais robusta de fazer isso é por meio de hardware especializado. Há um longo histórico de uso de módulos de segurança de hardware (HSMs) para gerar, armazenar e processar chaves para aplicativos críticos de segurança. Os cartões inteligentes são um tipo especial de HSM, assim como os dispositivos compatíveis com o padrão TPM do Trusted Computing Group. Sempre que possível, a implementação do Windows Hello aproveita o hardware TPM integrado para gerar, armazenar e processar chaves. No entanto, Windows Hello e Windows Hello para Trabalho não exigem um TPM integrado.

Sempre que possível, a Microsoft recomenda o uso de hardware TPM. O TPM protege contra uma variedade de ataques conhecidos e potenciais, incluindo ataques de força bruta PIN. O TPM também fornece uma camada adicional de proteção após um bloqueio de conta. Quando o TPM tiver bloqueado o material da chave, o usuário deverá redefinir o PIN. Redefinir o PIN significa que todas as chaves e certificados criptografados com o material de chave antigo serão removidos.

Autenticação

Quando um usuário deseja acessar o material de chave protegida, o processo de autenticação começa com o usuário inserindo um PIN ou gesto biométrico para desbloquear o dispositivo, um processo às vezes chamado de "liberação da chave".

Um aplicativo nunca pode usar as chaves de outro aplicativo, nem alguém pode usar as chaves de outro usuário. Essas chaves são usadas para assinar solicitações enviadas ao provedor de identidade ou IDP, buscando acesso a recursos especificados. Os aplicativos podem usar APIs específicas para solicitar operações que exigem material de chave para ações específicas. O acesso por meio dessas APIs requer validação explícita por meio de um gesto do usuário e o material de chave não é exposto ao aplicativo solicitante. Em vez disso, o aplicativo solicita uma ação específica, como assinar um dado, e a camada Windows Hello manipula o trabalho real e retorna os resultados.

Preparando-se para implementar o Windows Hello

Agora que temos uma compreensão básica de como o Windows Hello funciona, vamos dar uma olhada em como implementá-los em nossos próprios aplicativos.

Há diferentes cenários que podemos implementar usando o Windows Hello. Por exemplo, basta fazer logon no seu aplicativo em um dispositivo. O outro cenário comum seria autenticar em um serviço. Em vez de usar um nome de logon e senha, você usará o Windows Hello. Nas seções a seguir, discutiremos a implementação de alguns cenários diferentes, incluindo como autenticar em seus serviços com o Windows Hello e como converter de um sistema de nome de usuário/senha existente para um sistema Windows Hello.

Implementando o Windows Hello

Nesta seção, começamos com um cenário greenfield sem nenhum sistema de autenticação existente e explicamos como implementar o Windows Hello.

A próxima seção aborda como migrar de um sistema de nome de usuário/senha existente. No entanto, mesmo que essa seção lhe interesse mais, você pode querer dar uma olhada nesta para obter uma compreensão básica do processo e do código necessário.

Inscrevendo novos usuários

Começamos com um novo serviço que usará o Windows Hello e um novo usuário hipotético que está pronto para se inscrever em um novo dispositivo.

A primeira etapa é verificar se o usuário é capaz de usar o Windows Hello. O aplicativo verifica as configurações do usuário e os recursos da máquina para garantir que ele possa criar chaves de ID do usuário. Se o aplicativo determinar que o usuário ainda não habilitou o Windows Hello, ele solicitará que o usuário configure isso antes de usar o aplicativo.

Para habilitar o Windows Hello, o usuário só precisa configurar um PIN nas configurações do Windows, a menos que o usuário o configure durante a OOBE (Out of Box Experience).

As linhas de código a seguir mostram uma maneira simples de verificar se o usuário está configurado para o Windows Hello.

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

A próxima etapa é solicitar informações ao usuário para se inscrever no seu serviço. Você pode optar por solicitar ao usuário nome, sobrenome, endereço de e-mail e um nome de usuário exclusivo. Você pode usar o endereço de e-mail como identificador exclusivo; depende de você.

Nesse cenário, usamos o endereço de email como o identificador exclusivo do usuário. Depois que o usuário se inscrever, considere enviar um e-mail de validação para garantir que o endereço seja válido. Isso lhe dá um mecanismo para redefinir a conta, se necessário.

Se o usuário tiver configurado seu PIN, o aplicativo criará o KeyCredential do usuário. O aplicativo também obtém as informações opcionais de atestado de chave para adquirir uma prova criptográfica de que a chave é gerada no TPM. A chave pública gerada e, opcionalmente, o atestado, é enviada ao servidor de back-end para registrar o dispositivo que está sendo usado. Cada par de chaves gerado em cada dispositivo será único.

O código para criar o KeyCredential tem esta aparência:

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

O RequestCreateAsync é a chamada que cria a chave pública e privada. Se o dispositivo tiver o chip TPM correto, as APIs solicitarão que o chip TPM crie a chave privada e pública e armazene o resultado; se não houver nenhum chip TPM disponível, o sistema operacional criará o par de chaves no código. Não há como o aplicativo acessar as chaves privadas criadas diretamente. Parte da criação dos pares de chaves também são as informações de atestado resultantes. (Consulte a próxima seção para obter mais informações sobre atestado.)

Depois que o par de chaves e as informações de atestado são criados no dispositivo, a chave pública, as informações de atestado opcionais e o identificador exclusivo (como o endereço de email) precisam ser enviados ao serviço de registro de back-end e armazenados no back-end.

Para permitir que o usuário acesse o aplicativo em vários dispositivos, o serviço de back-end precisa ser capaz de armazenar várias chaves para o mesmo usuário. Como cada chave é única para cada dispositivo, armazenaremos todas essas chaves conectadas ao mesmo usuário. Um identificador de dispositivo é usado para ajudar a otimizar a parte do servidor ao autenticar usuários. Falaremos sobre isso com mais detalhes na próxima seção.

Um esquema de banco de dados de exemplo para armazenar essas informações no back-end pode ter esta aparência:

Esquema de banco de dados de exemplo do Windows Hello

A lógica de registro pode ser semelhante a esta:

Lógica de registro do Windows Hello

As informações de registro que você coleta podem, é claro, incluir muito mais informações de identificação do que incluímos neste cenário simples. Por exemplo, se seu aplicativo acessar um serviço seguro, como um para bancos, você precisará solicitar prova de identidade e outras coisas como parte do processo de inscrição. Uma vez atendidas todas as condições, a chave pública desse usuário será armazenada no backend e usada para validar na próxima vez que o usuário usar o serviço.

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.
    }
}

Atestado

Ao criar o par de chaves, também há uma opção para solicitar as informações de atestado, que são geradas pelo chip TPM. Essas informações opcionais podem ser enviadas ao servidor como parte do processo de inscrição. O atestado de chave TPM é um protocolo que prova criptograficamente que uma chave está associada ao TPM. Esse tipo de atestado pode ser usado para garantir que uma determinada operação criptográfica ocorreu no TPM de um computador específico.

Quando recebe a chave RSA gerada, a instrução de atestado e o certificado AIK, o servidor verifica as seguintes condições:

  • A assinatura do certificado AIK é válida.
  • O certificado AIK é encadeado a uma raiz confiável.
  • O certificado AIK e sua cadeia estão habilitados para EKU OID "2.23.133.8.3" (o nome amigável é "Certificado de Chave de Identidade de Atestado").
  • O certificado AIK é válido por tempo.
  • Todos os certificados de CA emissores na cadeia são válidos por tempo e não são revogados.
  • A instrução de atestado é formada corretamente.
  • A assinatura no blob KeyAttestation usa uma chave pública AIK.
  • A chave pública incluída no blob KeyAttestation corresponde à chave RSA pública que o cliente enviou junto com a instrução de atestado.

Seu aplicativo pode atribuir ao usuário um nível de autorização diferente, dependendo dessas condições. Por exemplo, se uma dessas verificações falhar, ela pode não registrar o usuário ou pode limitar o que o usuário pode fazer.

Fazendo logon com o Windows Hello

Depois que o usuário estiver inscrito em seu sistema, ele poderá usar o aplicativo. Dependendo do cenário, você pode pedir aos usuários que se autentiquem antes de começarem a usar o aplicativo ou apenas pedir que eles se autentiquem assim que começarem a usar seus serviços de back-end.

Forçar o usuário a entrar novamente

Para alguns cenários, talvez você queira que o usuário prove que é a pessoa que está conectada no momento, antes de acessar o aplicativo ou, às vezes, antes de executar uma determinada ação dentro do aplicativo. Por exemplo, antes que um aplicativo bancário envie o comando de transferência de dinheiro para o servidor, você deseja ter certeza de que é o usuário, e não alguém que encontrou um dispositivo conectado, tentando realizar uma transação. Você pode forçar o usuário a entrar novamente em seu aplicativo usando a classe UserConsentVerifier . A linha de código a seguir forçará o usuário a inserir suas credenciais.

A linha de código a seguir forçará o usuário a inserir suas credenciais.

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

Você também pode usar o mecanismo de resposta ao desafio do servidor, que exige que um usuário insira seu código PIN ou credenciais biométricas. Depende do cenário que você, como desenvolvedor, precisa implementar. Esse mecanismo é descrito na seção a seguir.

Autenticação no back-end

Quando o aplicativo tenta acessar um serviço de back-end protegido, o serviço envia um desafio para o aplicativo. O aplicativo usa a chave privada do usuário para assinar o desafio e o envia de volta ao servidor. Como o servidor armazenou a chave pública para esse usuário, ele usa APIs de criptografia padrão para garantir que a mensagem foi realmente assinada com a chave privada correta. No cliente, a assinatura é feita pelas APIs do Windows Hello; O desenvolvedor nunca terá acesso à chave privada de nenhum usuário.

Além de verificar as chaves, o serviço também pode verificar o atestado de chave e discernir se há alguma limitação invocada sobre como as chaves são armazenadas no dispositivo. Por exemplo, quando o dispositivo usa o TPM para proteger as chaves, ele é mais seguro do que os dispositivos que armazenam as chaves sem o TPM. A lógica de back-end pode decidir, por exemplo, que o usuário só tem permissão para transferir uma determinada quantia de dinheiro quando nenhum TPM é usado para reduzir os riscos.

O atestado só está disponível para dispositivos com um chip TPM versão 2.0 ou posterior. Portanto, você precisa levar em consideração que essas informações podem não estar disponíveis em todos os dispositivos.

O fluxo de trabalho do cliente pode ser semelhante ao seguinte gráfico:

Fluxo de trabalho do cliente Windows Hello

Quando o aplicativo chama o serviço no back-end, o servidor envia um desafio. O desafio é assinado com o seguinte código:

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)
    {

    }
}

A primeira linha, KeyCredentialManager.OpenAsync, solicitará que o Windows abra o identificador de chave. Se isso for bem-sucedido, você poderá assinar a mensagem de desafio com o método KeyCredential.RequestSignAsync , fazendo com que o Windows solicite o PIN ou a biometria do usuário por meio do Windows Hello. Em nenhum momento o desenvolvedor terá acesso à chave privada do usuário. Tudo isso é mantido em segurança por meio das APIs.

As APIs solicitam que o Windows assine o desafio com a chave privada. Em seguida, o sistema solicita ao usuário um código PIN ou um logon biométrico configurado. Quando as informações corretas são inseridas, o sistema pode solicitar que o chip TPM execute as funções criptográficas e assine o desafio. (Ou use a solução de software de fallback, se nenhum TPM estiver disponível). O cliente deve enviar o desafio assinado de volta ao servidor.

Um fluxo básico de desafio-resposta é mostrado neste diagrama de sequência:

Resposta ao desafio do Windows Hello

Em seguida, o servidor deve validar a assinatura. Quando você solicita a chave pública e a envia ao servidor para uso em validação futura, ela está em um blob publicKeyInfo codificado em ASN.1. Se você examinar o exemplo de código do Windows Hello no GitHub, verá que há classes auxiliares para encapsular funções Crypt32 para converter o blob codificado em ASN.1 em um blob CNG, que é mais comumente usado. O blob contém o algoritmo de chave pública, que é RSA, e a chave pública RSA.

No exemplo, o motivo pelo qual convertemos o blob codificado em ASN.1 em um blob CNG é para que ele possa ser usado com CNG e a API BCrypt. Se você pesquisar o blob CNG, ele apontará para a estrutura BCRYPT_KEY_BLOB relacionada. Essa superfície de API pode ser usada para autenticação e criptografia em aplicativos do Windows. ASN.1 é um padrão documentado para comunicar estruturas de dados que podem ser serializadas e é comumente usado em criptografia de chave pública e com certificados. É por isso que as informações de chave pública são retornadas dessa maneira. A chave pública é uma chave RSA; e esse é o algoritmo que o Windows Hello usa quando assina dados.

Depois de ter o blob CNG, você precisará validar o desafio assinado em relação à chave pública do usuário. Como cada um usa seu próprio sistema ou tecnologia de back-end, não há uma maneira genérica de implementar essa lógica. Estamos usando SHA256 como o algoritmo de hash e Pkcs1 para SignaturePadding, portanto, certifique-se de que é isso que você usa ao validar a resposta assinada do cliente. Novamente, consulte o exemplo para obter uma maneira de fazer isso em seu servidor no .NET 4.6, mas, em geral, será semelhante a este:

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

Lemos a chave pública armazenada, que é uma chave RSA. Validamos a mensagem de desafio assinada com a chave pública e, se isso for verificado, autorizamos o usuário. Se o usuário for autenticado, o aplicativo poderá chamar os serviços de back-end normalmente.

O código completo pode ser semelhante ao seguinte:

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;
    }
}

A implementação do mecanismo correto de desafio-resposta está fora do escopo deste documento, mas esse tópico é algo que requer atenção para criar com êxito um mecanismo seguro para evitar coisas como ataques de repetição ou ataques man-in-the-middle.

Registrando outro dispositivo

É comum que os usuários tenham vários dispositivos com os mesmos aplicativos instalados hoje. Como isso funciona ao usar o Windows Hello com vários dispositivos?

Ao usar o Windows Hello, cada dispositivo criará um conjunto exclusivo de chaves públicas e privadas. Isso significa que, se você quiser que um usuário possa usar vários dispositivos, seu back-end deverá ser capaz de armazenar várias chaves públicas desse usuário. Consulte o diagrama de banco de dados na seção Registrando novos usuários para obter um exemplo da estrutura da tabela.

Registrar outro dispositivo é quase o mesmo que registrar um usuário pela primeira vez. Você ainda precisa garantir que o usuário que se registra para este novo dispositivo seja realmente o usuário que afirma ser. Você pode fazer isso com qualquer mecanismo de autenticação de dois fatores usado hoje. Existem várias maneiras de fazer isso de maneira segura. Tudo depende do seu cenário.

Por exemplo, se você ainda usa o nome de login e a senha, pode usá-los para autenticar o usuário e solicitar que ele use um de seus métodos de verificação, como SMS ou e-mail. Se você não tiver um nome de login e senha, também poderá usar um dos dispositivos já registrados e enviar uma notificação para o aplicativo nesse dispositivo. O aplicativo autenticador MSA é um exemplo disso. Resumindo, você deve usar um mecanismo 2FA comum para registrar dispositivos extras para o usuário.

O código para registrar o novo dispositivo é exatamente o mesmo que registrar o usuário pela primeira vez (de dentro do aplicativo).

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

Para facilitar o reconhecimento do usuário sobre quais dispositivos estão registrados, você pode optar por enviar o nome do dispositivo ou outro identificador como parte do registro. Isso também é útil, por exemplo, se você quiser implementar um serviço em seu back-end em que os usuários possam cancelar o registro de dispositivos quando um dispositivo for perdido.

Usando várias contas em seu aplicativo

Além de oferecer suporte a vários dispositivos para uma única conta, também é comum oferecer suporte a várias contas em um único aplicativo. Por exemplo, talvez você esteja se conectando a várias contas do Twitter de dentro do seu aplicativo. Com o Windows Hello, você pode criar vários pares de chaves e dar suporte a várias contas dentro do seu aplicativo.

Uma maneira de fazer isso é manter o nome de usuário ou identificador exclusivo descrito na seção anterior sobre armazenamento isolado. Portanto, toda vez que você cria uma nova conta, armazena a ID da conta em armazenamento isolado.

Na interface do usuário do aplicativo, você permite que o usuário escolha uma das contas criadas anteriormente ou se inscreva com uma nova. O fluxo de criação de uma nova conta é o mesmo descrito anteriormente. Escolher uma conta é uma questão de listar as contas armazenadas na tela. Depois que o usuário selecionar uma conta, use o ID da conta para fazer logon no seu aplicativo:

var openKeyResult = await KeyCredentialManager.OpenAsync(AccountId);

O resto do fluxo é o mesmo descrito anteriormente. Para ser claro, todas essas contas são protegidas pelo mesmo PIN ou gesto biométrico, pois neste cenário estão sendo usadas em um único dispositivo com a mesma conta do Windows.

Migrando um sistema existente para o Windows Hello

Nesta breve seção, abordaremos um aplicativo empacotado existente e um sistema de back-end que usa um banco de dados que armazena o nome de usuário e a senha com hash. Esses aplicativos coletam credenciais do usuário quando o aplicativo é iniciado e as usam quando o sistema de back-end retorna o desafio de autenticação.

Aqui, descreveremos quais peças precisam ser alteradas ou substituídas para que o Windows Hello funcione.

Já descrevemos a maioria das técnicas nas seções anteriores. Adicionar o Windows Hello ao seu sistema existente envolve a adição de alguns fluxos diferentes na parte de registro e autenticação do seu código.

Uma abordagem é permitir que o usuário escolha quando atualizar. Depois que o usuário fizer logon no aplicativo e você detectar que o aplicativo e o sistema operacional são capazes de dar suporte ao Windows Hello, você poderá perguntar ao usuário se ele deseja atualizar as credenciais para usar esse sistema moderno e mais seguro. Você pode usar o código a seguir para verificar se o usuário é capaz de usar o Windows Hello.

var keyCredentialAvailable = await KeyCredentialManager.IsSupportedAsync();

A interface do usuário pode ser semelhante a esta:

Uma captura de tela da interface do usuário do Windows Hello

Se o usuário optar por começar a usar o Windows Hello, você criará o KeyCredential descrito anteriormente. O servidor de registro de back-end adiciona a chave pública e a instrução de atestado opcional ao banco de dados. Como o usuário já está autenticado com nome de usuário e senha, o servidor pode vincular as novas credenciais às informações do usuário atual no banco de dados. O modelo de banco de dados pode ser o mesmo que o exemplo descrito anteriormente.

Se o aplicativo foi capaz de criar o KeyCredential dos usuários, ele armazena a ID do usuário em armazenamento isolado para que o usuário possa escolher essa conta na lista assim que o aplicativo for iniciado novamente. Desse ponto em diante, o fluxo segue exatamente os exemplos descritos nas seções anteriores.

A etapa final na migração para um cenário completo do Windows Hello é desabilitar a opção de nome e senha de logon no aplicativo e remover as senhas com hash armazenadas do banco de dados.

Resumo

O Windows apresenta um nível mais alto de segurança que também é simples de colocar em prática. O Windows Hello fornece um novo sistema de entrada biométrico que reconhece o usuário e nulifica ativamente os esforços para contornar a identificação adequada. Ele pode fornecer várias camadas de chaves e certificados que nunca podem ser revelados ou usados fora do módulo de plataforma confiável. Além disso, uma camada adicional de segurança está disponível por meio do uso opcional de chaves de identidade e certificados de atestado.

Como desenvolvedor, você pode usar essas diretrizes sobre design e implantação dessas tecnologias para adicionar facilmente autenticação segura às distribuições de aplicativos do Windows empacotados para proteger aplicativos e serviços de back-end. O código necessário é mínimo e fácil de entender. O Windows lida com o trabalho pesado.

As opções de implementação flexíveis permitem que o Windows Hello substitua ou trabalhe junto com o sistema de autenticação existente. A experiência de implantação é indolor e econômica. Nenhuma infraestrutura adicional é necessária para implantar a segurança do Windows. Com o Microsoft Hello integrado ao sistema operacional, o Windows oferece a solução mais segura para os problemas de autenticação enfrentados pelo desenvolvedor moderno.

Missão cumprida! Você acabou de tornar a Internet um lugar mais seguro!

Recursos adicionais

Artigos e código de exemplo

Terminologia

Termo Definição
AIK Uma chave de identidade de atestado é usada para fornecer essa prova criptográfica (atestado de chave TPM) assinando as propriedades da chave não migrável e fornecendo as propriedades e a assinatura à terceira parte confiável para verificação. A assinatura resultante é chamada de "declaração de atestado". Como a assinatura é criada usando a chave privada AIK, que só pode ser usada no TPM que a criou, a terceira parte confiável pode confiar que a chave atestada é realmente não migrável e não pode ser usada fora desse TPM.
Certificado AIK Um certificado AIK é usado para atestar a presença de um AIK em um TPM. Ele também é usado para atestar que outras chaves certificadas pelo AIK se originaram desse TPM específico.
IDP Um IDP é um provedor de identidade. Um exemplo é o build do IDP pela Microsoft para contas da Microsoft. Sempre que um aplicativo precisa se autenticar com um MSA, ele pode chamar o IDP do MSA.
PKI A infraestrutura de chave pública é comumente usada para apontar para um ambiente hospedado por uma própria organização e ser responsável por criar chaves, revogar chaves, etc.
TPM O módulo de plataforma confiável pode ser usado para criar pares de chaves públicas/privadas criptográficas de forma que a chave privada nunca possa ser revelada ou usada fora do TPM (ou seja, a chave não é migrável).
Atestado de chave de TPM Um protocolo que prova criptograficamente que uma chave está associada ao TPM. Esse tipo de atestado pode ser usado para garantir que uma determinada operação criptográfica ocorreu no TPM de um determinado computador