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ões inteligentes físicos, criar cartões inteligentes virtuais, se comunicar com cartões inteligentes, autenticar usuários, redefinir PINs de usuário e remover ou desconectar cartões inteligentes.

As APIs do Tempo de Execução do Windows (WinRT) para cartões inteligentes fazem parte do Windows Software Development Kit (SDK). Essas APIs foram criadas para uso em aplicativos da Plataforma Universal do Windows (UWP), mas também podem ser usadas em aplicativos WinUI ou em pacotes de aplicativos da área de trabalho, 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 o recurso Certificados de Usuário Compartilhados no arquivo Package.appxmanifest do projeto WinUI ou projeto de empacotamento.

Aceda a leitores de cartões conectados e cartões inteligentes

Você pode consultar leitores e cartões inteligentes anexados passando o ID do dispositivo (especificado em DeviceInformation) para o método SmartCardReader.FromIdAsync . Para acessar os cartões inteligentes atualmente conectados 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 habilitar seu aplicativo para observar eventos CardAdded implementando um método para manipular 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 precisará primeiro fornecer um nome amigável, uma chave de administrador e uma 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 os três valores para RequestVirtualSmartCardCreationAsync.

  1. Criar uma nova instância de um SmartCardPinPolicy
  2. Gere o valor da chave admin chamando CryptographicBuffer.GenerateRandom no valor da chave admin 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 de RequestVirtualSmartCardCreationAsync retornar o objeto SmartCardProvisioning associado, o cartão inteligente virtual é provisionado e está pronto para utilização.

Observação

Para criar um cartão inteligente virtual usando um aplicativo do 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 de 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 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.

Obter a chave de administração

Antes de executar a autenticação, você precisa obter a chave de administrador. A origem da chave admin depende do seu cenário:

  • Para cartões inteligentes virtuais que você criou: use a mesma chave de administrador que foi gerada durante a criação do cartão (conforme mostrado na seção "Criar um cartão inteligente virtual" acima). Você deve armazenar essa chave de forma segura para uso posterior de autenticação.
  • Para cartões inteligentes físicos ou virtuais existentes: a chave de administrador é normalmente fornecida pelo departamento de TI da sua organização, pelo sistema de gestão de cartões ou pelo serviço que emitiu o cartão.
  • Para desenvolvimento/teste: Você pode gerar uma chave de administração de teste usando CryptographicBuffer.GenerateRandom como mostrado no exemplo de criação de cartão virtual abaixo.
// Example: Store the admin key from virtual card creation for later use
IBuffer adminkey = CryptographicBuffer.GenerateRandom(24);

// Store this key securely in your app (e.g., in app settings, secure storage, etc.)
// You'll need this same key for authentication operations

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

// Save the adminkey for future authentication
SaveAdminKeySecurely(adminkey);

Exemplo de métodos de gerenciamento de chaves de administração

Aqui estão exemplos de métodos que você pode implementar para armazenar e recuperar chaves de administrador com segurança:

// Example implementation for storing admin key securely
private void SaveAdminKeySecurely(IBuffer adminKey)
{
    // Convert to string for storage (consider encryption for production)
    string adminKeyString = CryptographicBuffer.EncodeToBase64String(adminKey);
    
    // Store in app settings (consider using Windows Credential Manager for production)
    ApplicationData.Current.LocalSettings.Values["SmartCardAdminKey"] = adminKeyString;
}

// Example implementation for retrieving stored admin key
private IBuffer GetStoredAdminKey()
{
    // Retrieve from app settings
    string adminKeyString = ApplicationData.Current.LocalSettings.Values["SmartCardAdminKey"] as string;
    
    if (string.IsNullOrEmpty(adminKeyString))
    {
        throw new InvalidOperationException("Admin key not found. Ensure the smart card was created by this app or the admin key was provided by your IT department.");
    }
    
    // Convert back to IBuffer
    return CryptographicBuffer.DecodeFromBase64String(adminKeyString);
}

Algoritmo de autenticação

O código a seguir mostra como oferecer 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 administração no cartão ("desafio") forem os mesmos que os dados da chave de administração fornecidos pelo servidor ou pela ferramenta de gerenciamento ("chave de administração"), 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 ao longo do restante deste tópico, pois analisamos 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 começar 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 de desafio do cartão e a chave admin 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();

// Use the admin key that was either:
// 1. Generated during virtual card creation, or
// 2. Provided by your IT department/card management system
IBuffer adminKey = GetStoredAdminKey(); // Your method to retrieve the stored admin key

IBuffer response = ChallengeResponseAlgorithm.CalculateResponse(
    context.Challenge,
    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 reposição do PIN:

  1. Chame RequestPinResetAsync para iniciar a operação. Esta 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
        {
            // Use the same admin key from card creation or your secure storage
            IBuffer adminKey = GetStoredAdminKey(); // Your method to retrieve the stored admin key
            
            IBuffer response =
                ChallengeResponseAlgorithm.CalculateResponse(
                    request.Challenge,
                    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 disparo desse evento ao leitor de cartões com o método que define o comportamento do seu aplicativo como um manipulador de eventos na remoção do cartão ou do leitor. 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);