Partilhar via


Oi do Windows

Este artigo descreve a tecnologia Windows Hello 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 decorrentes do uso de credenciais convencionais e fornece orientação sobre como projetar e implantar essas tecnologias como parte de uma implantaçã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 for Business.

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

Introdução

Um pressuposto fundamental sobre segurança da informação é que um sistema pode identificar quem o 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 informáticos implantados em todo o mundo depende das credenciais dos utilizadores para tomar decisões de autenticação e autorização, o que significa que estes sistemas dependem de palavras-passe reutilizáveis criadas pelo utilizador como base para a 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 a questão: 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 de usuários. Com o tempo, o state-of-the-art 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, 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 facilmente. Todos os locais onde uma palavra-passe é introduzida, processada ou armazenada são vulneráveis. 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 pressionamentos de teclas do usuário em um dispositivo ou observando para ver quais caracteres um usuário digita. Estes são apenas os métodos de ataque mais comuns.

Outro risco relacionado é o da repetição de credenciais, em que um invasor captura uma credencial válida por meio de escutas em uma rede insegura e, em seguida, a reproduz mais tarde para se passar por um usuário válido. A maioria dos protocolos de autenticação (incluindo Kerberos e OAuth) protege contra ataques de repetiçã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 ruim. Um invasor que recuperar com êxito um par de nome de usuário e senha de um sistema comprometido pode tentar esse mesmo par em outros sistemas. Esta tática funciona surpreendentemente muitas vezes para permitir que os atacantes 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 palavras-passe colocam é complicado. Apenas reforçar as políticas de senha não resolverá o problema; os utilizadores podem simplesmente reciclar, partilhar ou anotar as senhas. Embora a educação do usuário seja fundamental para a segurança da autenticação, a educação por si só também não elimina o problema.

O Windows Hello substitui as senhas por autenticação forte de dois fatores (2FA) 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?

O Windows Hello é um sistema de início de sessão biométrico incorporado no Windows que lhe permite utilizar o rosto, a impressão digital ou um PIN para desbloquear o dispositivo. Ele substitui as senhas tradicionais por um método mais seguro e conveniente. Os seus dados biométricos são armazenados de forma segura no seu dispositivo e, mesmo que alguém roube o seu dispositivo, não pode aceder ao mesmo sem o seu PIN ou gesto biométrico. Uma vez desbloqueado, pode aceder às suas aplicações, dados e serviços sem problemas.

O autenticador do Windows Hello é conhecido como Olá. Cada Hello é exclusivo para um usuário e dispositivo específico. Não sincroniza entre dispositivos nem partilha dados com servidores ou aplicações. Se várias pessoas usarem o mesmo dispositivo, cada pessoa precisará configurar sua própria configuração do Windows Hello. Essa configuração está vinculada às suas credenciais nesse dispositivo específico. Pense em um Hello como uma chave que desbloqueia suas credenciais armazenadas, que são usadas para entrar em aplicativos ou serviços. Não é uma credencial em si, mas atua como uma segunda camada de segurança durante a 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 deve conceder acesso a um recurso solicitado. O Windows Hello fornece 2FA forte que é totalmente integrado 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 é realizada usando primitivas criptográficas em vez de comparações de cadeia de caracteres, e o material da chave do usuário é seguro dentro de hardware inviolável. O Windows Hello também não requer os componentes de infraestrutura adicionais 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. 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 sua máquina, ele gera um novo par de chaves público-privado no dispositivo. O módulo de plataforma fiável (TPM) gera e protege essa chave privada. Se o dispositivo não tiver um chip TPM, a chave privada é encriptada 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á vinculada 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 da Microsoft conectada nas configurações do Windows.

Como as chaves são protegidas

Sempre que o material chave é gerado, ele deve ser protegido contra ataques. A maneira mais robusta de fazer isso é através de hardware especializado. Há uma longa história 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, o Windows Hello e o Windows Hello for Work 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 utilizador deverá alterar 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 "liberar a 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 que são 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 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 da chave não é exposto ao aplicativo solicitante. Em vez disso, o aplicativo solicita uma ação específica, como assinar um pedaço de dados, e a camada do Windows Hello lida com 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.

Existem 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 num serviço. Em vez de usar um nome de logon e senha, você estará usando 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 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 olhar através deste para obter uma compreensão básica do processo e do código necessário.

Inscrever novos utilizadores

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

O primeiro passo é 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 de 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 utilizador só precisa configurar um PIN nas definições do Windows, a menos que o tenha configurado durante o Out of Box Experience (OOBE).

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

O próximo passo é pedir informações ao usuário para se inscrever no seu serviço. Você pode optar por pedir 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 si.

Nesse cenário, usamos o endereço de email como o identificador exclusivo para o usuário. Depois que o usuário se inscrever, você deve considerar o envio de 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 configurou seu PIN, o aplicativo cria a KeyCredential do usuário. O aplicativo também obtém as informações opcionais de atestado de chave para adquirir prova criptográfica de que a chave é gerada no TPM. A chave pública gerada e, opcionalmente, o atestado, é enviada para o servidor 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 a 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 certo, as APIs solicitarão o chip TPM para criar a chave privada e pública e armazenar 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 a informação de atestado resultante. (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 criadas no dispositivo, a chave pública, as informações de atestado opcionais e o identificador exclusivo (como o endereço de e-mail) precisam ser enviados para o 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 registo pode ter o seguinte aspeto:

Lógica de registo 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 um comprovante de identidade e outras coisas como parte do processo de inscrição. Uma vez cumpridas todas as condições, a chave pública deste utilizador será armazenada no back-end e utilizada para validar da próxima vez que o utilizador utilizar 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, há também 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á ligada ao TPM. Este tipo de atestado pode ser usado para garantir que uma determinada operação criptográfica ocorreu no TPM de um determinado computador.

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 até uma raiz confiável.
  • O certificado AIK e a sua cadeia estão habilitados para o OID EKU "2.23.133.8.3" (o nome comum é "Attestation Identity Key Certificate").
  • O certificado AIK é válido por tempo.
  • Todos os certificados dos organismos emissores de certificação na cadeia são válidos em termos de tempo e não revogados.
  • A declaração de atestado está 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 declaraçã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.

Iniciar sessão com o Windows Hello

Uma vez que o usuário está inscrito em seu sistema, ele ou ela pode usar o aplicativo. Dependendo do cenário, você pode pedir aos usuários que se autentiquem antes que eles possam começar 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, você pode querer 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 seu aplicativo. Por exemplo, antes de um aplicativo bancário enviar o comando transferir dinheiro para o servidor, você quer ter certeza de que é o usuário, em vez de 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 a desafios 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. Este mecanismo é descrito na secção seguinte.

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 envia-o de volta para o 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 chaves e discernir se há alguma limitação invocada sobre como as chaves são armazenadas no dispositivo. Por exemplo, quando o dispositivo usa TPM para proteger as chaves, é mais seguro do que dispositivos que armazenam as chaves sem TPM. A lógica de back-end pode decidir, por exemplo, que o usuário só pode transferir uma certa 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 conta que essas informações podem não estar disponíveis em todos os dispositivos.

O fluxo de trabalho do cliente pode se parecer com o 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, pedirá ao Windows para abrir o identificador de chave. Se isso for bem-sucedido, você pode 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 utilizador um código PIN ou um início de sessão biométrico configurado. Quando as informações corretas são inseridas, o sistema pode pedir ao chip TPM para executar as funções criptográficas e assinar o desafio. (Ou utilize a solução de software alternativa, 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 para o servidor a ser usada para 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 traduzir o blob codificado em ASN.1 para 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, a razão pela 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ê procurar o blob CNG, ele irá apontá-lo para a estrutura de 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 possuir o blob CNG, é necessário validar o desafio assinado contra a chave pública do utilizador. 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 quando valida a resposta assinada do cliente. Novamente, consulte o exemplo para obter uma maneira de fazê-lo em seu servidor no .NET 4.6, mas em geral ele terá a seguinte aparência:

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 estiver autenticado, o aplicativo poderá chamar os serviços de back-end normalmente.

O código completo pode ter a seguinte aparência:

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 este tópico é algo que requer atenção para criar com sucesso um mecanismo seguro para evitar coisas como ataques de repetição ou ataques man-in-the-middle.

Registar 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 deve 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 é realmente o usuário que afirma ser. Você pode fazer isso com qualquer mecanismo de autenticação de dois fatores usado atualmente. Existem várias maneiras de conseguir isso de forma segura. Tudo depende do seu cenário.

Por exemplo, se você ainda usa nome de login e senha, você pode usar isso para autenticar o usuário e pedir-lhe para usar um de seus métodos de verificação, como SMS ou e-mail. Se não tiver um nome de início de sessão e uma palavra-passe, também pode utilizar um dos dispositivos já registados e enviar uma notificação para a aplicação nesse dispositivo. O aplicativo autenticador MSA é um exemplo disso. Em suma, 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 tornar mais fácil para o usuário reconhecer 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 onde os usuários podem cancelar o registro de dispositivos quando um dispositivo é perdido.

Usando várias contas em seu aplicativo

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

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 o 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 usuário em seu aplicativo:

var openKeyResult = await KeyCredentialManager.OpenAsync(AccountId);

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

Migrando um sistema existente para o Windows Hello

Nesta pequena 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 fazer o Windows Hello funcionar.

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ê detetar que o aplicativo e o sistema operacional são capazes de suportar o Windows Hello, você pode 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 ter esta aparência:

Uma captura de ecrã da interface de utilizador do Windows Hello

Se o usuário optar por começar a usar o Windows Hello, você criará a KeyCredential descrita anteriormente. O servidor de registo de back-end adiciona a chave pública e a declaraçã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 atuais do usuário 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 os usuários KeyCredential, ele armazena o ID do usuário em armazenamento isolado para que o usuário possa escolher essa conta da lista assim que o aplicativo for iniciado novamente. A partir deste ponto, 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 de logon e senha no aplicativo e remover as senhas com hash armazenadas do banco de dados.

Resumo

O Windows introduz um nível mais elevado de segurança que também é simples de pôr em prática. O Windows Hello fornece um novo sistema de entrada biométrica que reconhece o usuário e derrota ativamente os esforços para contornar a identificação adequada. Em seguida, 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 outra camada de segurança está disponível através do uso opcional de chaves de identidade e certificados de atestado.

Como desenvolvedor, você pode usar estas diretrizes sobre design e implantação dessas tecnologias para adicionar facilmente autenticação segura às distribuições de aplicativos do Windows empacotadas 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 em conjunto com o seu 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

Período 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 do 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 é utilizado para atestar a existência de um AIK dentro de um TPM. Também é usado para atestar que outras chaves certificadas pelo AIK se originaram desse TPM específico.
Deslocados internos Um IDP é um provedor de identidade. Um exemplo é a compilação IDP da Microsoft para contas da Microsoft. Toda vez 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 pela própria organização e ser responsável por criar chaves, revogar chaves, etc.
Módulo de Plataforma Confiável (TPM) O módulo de plataforma confiável pode ser usado para criar pares criptográficos de chaves públicas/privadas de tal 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 TPM Um protocolo que prova criptograficamente que uma chave está ligada ao TPM. Este tipo de atestado pode ser usado para garantir que uma determinada operação criptográfica ocorreu no TPM de um determinado computador