Cartões inteligentes

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

Configurar o manifesto do aplicativo

Para que o seu aplicativo possa autenticar usuários usando cartões inteligentes ou cartões inteligentes virtuais, você deve configurar o recurso Certificados de Usuário Compartilhado no arquivo do projeto Package.appxmanifest.

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

Você pode consultar leitores e cartões inteligentes conectados passando a ID de dispositivo (especificada em DeviceInformation) para o método SmartCardReader.FromIdAsync. Para acessar os cartões inteligentes atualmente conectados a um 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ê deve também habilitar seu aplicativo para observar eventos CardAdded e implementar uma função para determinar 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 acessar os métodos que permitem ao seu aplicativo acessar e personalizar sua configuração.

Crie um cartão inteligente virtual

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

  1. Crie 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 pela ferramenta de gerenciamento.
  3. Passe esses valores junto com a cadeia FriendlyNameText para RequestVirtualSmartCardCreationAsync.
SmartCardPinPolicy pinPolicy = new SmartCardPinPolicy();
pinPolicy.MinLength = 6;

IBuffer adminkey = CryptographicBuffer.GenerateRandom(24);

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

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

Observação

Para criar uma cartão inteligente virtual usando um aplicativo UWP, 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 de cartão inteligente virtual falhará.

Trate os desafios da autenticação

Para autenticar com cartões inteligentes ou cartões inteligentes virtuais, o seu aplicativo deve fornecer o comportamento para concluir os desafios entre os dados da chave de administração armazenados no cartão e os dados da chave de administração mantidos pelo servidor de autenticação ou pela 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 do cartão físico ou virtual. Se os dados gerados usando a chave de administração no cartão ("desafio") forem iguais aos dados da chave de administração fornecidos pelo servidor ou pela 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 enquanto revisamos como concluir a ação de autenticação e como aplicar mudanças nas informações do cartão inteligente e do cartão inteligente virtual.

Verifique a resposta de autenticação do cartão inteligente ou do cartão inteligente virtual

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

  1. Para começar o desafio, chame GetChallengeContextAsync do objeto SmartCardProvisioning associado ao cartão inteligente. Isso irá gerar uma instância do 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 administração fornecidos pelo serviço ou pela ferramenta de gerenciamento ao 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);

using (SmartCardChallengeContext context =
       await provisioning.GetChallengeContextAsync())
{
    IBuffer response = ChallengeResponseAlgorithm.CalculateResponse(
        context.Challenge,
        rootPage.AdminKey);

    verifyResult = await context.VerifyResponseAsync(response);
}

Altere ou redefina um PIN do 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 que o usuário conclua 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 PIN.

  2. SmartCardPinResetHandler fornece informações de que nosso ChallengeResponseAlgorithm, encapsulado em uma chamada SmartCardPinResetDeferral, usa para comparar o valor do desafio do cartão e a chave de administração fornecida pelo serviço ou pela ferramenta de gerenciamento para autenticar a solicitação.

  3. Se o desafio for bem-sucedido, a chamada RequestPinResetAsync estará concluída; retornando true se o PIN teve uma redefinição bem-sucedida.

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

Remova um cartão inteligente ou um cartão inteligente virtual

Quando um cartão inteligente físico é removido, um evento CardRemoved é disparado quando o cartão é excluído.

Associe o disparo desse evento ao leitor de cartão ao método que define o comportamento do seu 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 de forma programática, primeiro recuperando o cartão e, em seguida, chamando RequestVirtualSmartCardDeletionAsync a partir do objeto retornado SmartCardProvisioning.

bool result = await SmartCardProvisioning
    .RequestVirtualSmartCardDeletionAsync(card);