Partilhar via


Cartões inteligentes

Este tópico explica como os aplicativos do Windows podem usar cartões inteligentes para conectar usuários a serviços de rede seguros, incluindo como acessar leitores de cartão inteligente físicos, criar cartões inteligentes virtuais, comunicar-se com cartões inteligentes, autenticar usuários, redefinir PINs de usuário e remover ou desconectar cartões inteligentes.

As APIs do WinRT (Tempo de Execução do Windows) para cartões inteligentes fazem parte do SDK (Software Development Kit) do Windows. Essas APIs foram criadas para uso em aplicativos UWP (Plataforma Universal do Windows), mas também podem ser usadas em aplicativos WinUI ou em aplicativos da área de trabalho empacotados, incluindo WPF e Windows Forms. Para obter mais informações sobre como usar APIs do WinRT em seu aplicativo da área de trabalho do Windows, consulte Chamar APIs do Tempo de Execução do Windows em aplicativos da área de trabalho.

Configurar o manifesto do aplicativo

Antes que seu aplicativo possa autenticar usuários usando cartões inteligentes ou cartões inteligentes virtuais, você deve definir a funcionalidade Certificados de Usuário Compartilhados no arquivo Package.appxmanifest do projeto WinUI ou do projeto de empacotamento.

Acesse leitores de cartão conectados e cartões inteligentes

Você pode consultar leitores e cartões inteligentes anexados passando a ID do dispositivo (especificada em DeviceInformation) para o método SmartCardReader.FromIdAsync . Para acessar os cartões inteligentes atualmente anexados ao dispositivo leitor retornado, chame SmartCardReader.FindAllCardsAsync.

string selector = SmartCardReader.GetDeviceSelector();
DeviceInformationCollection devices =
    await DeviceInformation.FindAllAsync(selector);

foreach (DeviceInformation device in devices)
{
    SmartCardReader reader =
        await SmartCardReader.FromIdAsync(device.Id);

    // For each reader, we want to find all the cards associated
    // with it. Then we will create a SmartCardListItem for
    // each (reader, card) pair.
    IReadOnlyList<SmartCard> cards =
        await reader.FindAllCardsAsync();
}

Você também deve permitir que seu aplicativo observe eventos CardAdded implementando um método para lidar com o comportamento do aplicativo na inserção do cartão.

private void reader_CardAdded(SmartCardReader sender, CardAddedEventArgs args)
{
  // A card has been inserted into the sender SmartCardReader.
}

Em seguida, você pode passar cada objeto SmartCard retornado para SmartCardProvisioning para acessar os métodos que permitem que seu aplicativo acesse e personalize sua configuração.

Criar um cartão inteligente virtual

Para criar um cartão inteligente virtual usando SmartCardProvisioning, seu aplicativo primeiro precisará fornecer um nome amigável, uma chave de administrador e um SmartCardPinPolicy. O nome amigável geralmente é algo fornecido ao aplicativo, mas seu aplicativo ainda precisará fornecer uma chave de administrador e gerar uma instância do SmartCardPinPolicy atual antes de passar todos os três valores para RequestVirtualSmartCardCreationAsync.

  1. Criar uma nova instância de um SmartCardPinPolicy
  2. Gere o valor da chave de administração chamando CryptographicBuffer.GenerateRandom no valor da chave de administração fornecido pelo serviço ou ferramenta de gerenciamento.
  3. Passe esses valores junto com a cadeia de caracteres FriendlyNameText para RequestVirtualSmartCardCreationAsync.
var pinPolicy = new SmartCardPinPolicy
    {
        MinLength = 6
    };

IBuffer adminkey = CryptographicBuffer.GenerateRandom(24);

SmartCardProvisioning provisioning = await
     SmartCardProvisioning.RequestVirtualSmartCardCreationAsync(
          "Card friendly name",
          adminkey,
          pinPolicy);

Depois que RequestVirtualSmartCardCreationAsync retornar o objeto SmartCardProvisioning associado, o cartão inteligente virtual será provisionado e estará pronto para uso.

Observação

Para criar um cartão inteligente virtual usando um aplicativo Windows empacotado, o usuário que executa o aplicativo deve ser membro do grupo de administradores. Se o usuário não for membro do grupo de administradores, a criação do cartão inteligente virtual falhará.

Lidar com desafios de autenticação

Para autenticar com cartões inteligentes ou cartões inteligentes virtuais, seu aplicativo deve fornecer o comportamento para concluir desafios entre os dados da chave de administrador armazenados no cartão e os dados da chave de administrador mantidos pelo servidor de autenticação ou ferramenta de gerenciamento.

O código a seguir mostra como dar suporte à autenticação de cartão inteligente para serviços ou modificação de detalhes de cartão físico ou virtual. Se os dados gerados usando a chave de administrador no cartão ("desafio") forem os mesmos que os dados da chave de administração fornecidos pelo servidor ou ferramenta de gerenciamento ("adminkey"), a autenticação será bem-sucedida.

static class ChallengeResponseAlgorithm
{
    public static IBuffer CalculateResponse(IBuffer challenge, IBuffer adminkey)
    {
        if (challenge == null)
            throw new ArgumentNullException("challenge");
        if (adminkey == null)
            throw new ArgumentNullException("adminkey");

        SymmetricKeyAlgorithmProvider objAlg = SymmetricKeyAlgorithmProvider.OpenAlgorithm(SymmetricAlgorithmNames.TripleDesCbc);
        var symmetricKey = objAlg.CreateSymmetricKey(adminkey);
        var buffEncrypted = CryptographicEngine.Encrypt(symmetricKey, challenge, null);
        return buffEncrypted;
    }
}

Você verá esse código referenciado em todo o restante deste tópico, onde revisamos como concluir uma ação de autenticação e como aplicar alterações às informações do cartão inteligente e do cartão inteligente virtual.

Verificar a resposta de autenticação de cartão inteligente ou cartão inteligente virtual

Agora que temos a lógica para os desafios de autenticação definida, podemos nos comunicar com o leitor para acessar o cartão inteligente ou, alternativamente, acessar um cartão inteligente virtual para autenticação.

  1. Para iniciar o desafio, chame GetChallengeContextAsync do objeto SmartCardProvisioning associado ao cartão inteligente. Isso gerará uma instância de SmartCardChallengeContext, que contém o valor Challenge do cartão.
  2. Em seguida, passe o valor do desafio do cartão e a chave de administrador fornecida pelo serviço ou ferramenta de gerenciamento para o ChallengeResponseAlgorithm que definimos no exemplo anterior.
  3. VerifyResponseAsync retornará true se a autenticação for bem-sucedida.
bool verifyResult = false;
SmartCard card = await rootPage.GetSmartCard();
SmartCardProvisioning provisioning =
    await SmartCardProvisioning.FromSmartCardAsync(card);

SmartCardChallengeContext context =
    await provisioning.GetChallengeContextAsync();

IBuffer response = ChallengeResponseAlgorithm.CalculateResponse(
    context.Challenge,
    rootPage.AdminKey);

verifyResult = await context.VerifyResponseAsync(response);

Alterar ou redefinir um PIN de usuário

Para alterar o PIN associado a um cartão inteligente:

  1. Acesse o cartão e gere o objeto SmartCardProvisioning associado.
  2. Chame RequestPinChangeAsync para exibir uma interface do usuário para o usuário concluir essa operação.
  3. Se o PIN foi alterado com êxito, a chamada retornará true.
SmartCardProvisioning provisioning =
    await SmartCardProvisioning.FromSmartCardAsync(card);

bool result = await provisioning.RequestPinChangeAsync();

Para solicitar uma redefinição de PIN:

  1. Chame RequestPinResetAsync para iniciar a operação. Essa chamada inclui um método SmartCardPinResetHandler que representa o cartão inteligente e a solicitação de redefinição de pino.
  2. SmartCardPinResetHandler fornece informações que nosso ChallengeResponseAlgorithm, encapsulado em uma chamada SmartCardPinResetDeferral , usa para comparar o valor de desafio do cartão e a chave de administrador fornecida pelo serviço ou ferramenta de gerenciamento para autenticar a solicitação.
  3. Se o desafio for bem-sucedido, a chamada RequestPinResetAsync será concluída; retornando true se o PIN foi redefinido com êxito.
SmartCardProvisioning provisioning =
    await SmartCardProvisioning.FromSmartCardAsync(card);

bool result = await provisioning.RequestPinResetAsync(
    (pinResetSender, request) =>
    {
        SmartCardPinResetDeferral deferral =
            request.GetDeferral();

        try
        {
            IBuffer response =
                ChallengeResponseAlgorithm.CalculateResponse(
                    request.Challenge,
                    rootPage.AdminKey);
            request.SetResponse(response);
        }
        finally
        {
            deferral.Complete();
        }
    });
}

Remover um cartão inteligente ou um cartão inteligente virtual

Quando um cartão inteligente físico é removido, um evento CardRemoved será acionado quando o cartão for excluído.

Associe o acionamento desse evento ao leitor de cartão com o método que define o comportamento do aplicativo na remoção do cartão ou do leitor como um manipulador de eventos. Esse comportamento pode ser algo tão simples quanto fornecer notificação ao usuário de que o cartão foi removido.

reader = card.Reader;
reader.CardRemoved += HandleCardRemoved;

A remoção de um cartão inteligente virtual é tratada programaticamente recuperando primeiro o cartão e, em seguida, chamando RequestVirtualSmartCardDeletionAsync do objeto retornado SmartCardProvisioning .

bool result = await SmartCardProvisioning
    .RequestVirtualSmartCardDeletionAsync(card);