Smart card

Questo argomento illustra in che modo le app di Windows possono usare smart card per connettere gli utenti ai servizi di rete sicuri, tra cui come accedere ai lettori di smart card fisici, creare smart card virtuali, comunicare con smart card, autenticare gli utenti, reimpostare i PIN utente e rimuovere o disconnettere smart card.

Le API Windows Runtime (WinRT) per le smart card fanno parte di Windows Software Development Kit (SDK). Queste API sono state create per l'uso nelle app UWP (piattaforma UWP (Universal Windows Platform)), ma possono essere usate anche nelle app WinUI o nelle app desktop in pacchetto, tra cui WPF e Windows Form. Per altre informazioni sull'uso delle API WinRT nell'app desktop di Windows, vedi Chiamare le API di Windows Runtime nelle app desktop.

Configurare il manifesto dell'applicazione

Prima che l'app possa autenticare gli utenti usando smart card o smart card virtuali, è necessario impostare la funzionalità Certificati utente condivisi nel file package.appxmanifest del progetto WinUI o del progetto di creazione di pacchetti.

Accedere ai lettori di schede connesse e alle smart card

È possibile eseguire una query per i lettori e le smart card associate passando l'ID dispositivo (specificato in DeviceInformation) nel metodo SmartCardReader.FromIdAsync. Per accedere alle smart card attualmente collegate al dispositivo lettore restituito, chiamare 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();
}

Si deve anche abilitare l'app per osservare gli eventi CardAdded implementando un metodo per gestire il comportamento dell'app durante l'inserimento di schede.

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

È quindi possibile passare ogni oggetto SmartCard restituito a SmartCardProvisioning per accedere ai metodi che consentono all'app di accedere e personalizzarne la configurazione.

Creare una smart card virtuale

Per creare una smart card virtuale con SmartCardProvisioning, l'app dovrà prima specificare un nome descrittivo, una chiave amministratore e una SmartCardPinPolicy. Il nome descrittivo è in genere fornito all'app, ma l'app dovrà comunque fornire una chiave di amministratore e generare un'istanza dell'oggetto SmartCardPinPolicy prima di passare tutti e tre i valori a RequestVirtualSmartCardCreationAsync.

  1. Creare una nuova istanza di SmartCardPinPolicy
  2. Generare il valore della chiave amministratore chiamando CryptographicBuffer.GenerateRandom sul valore della chiave di amministrazione fornito dal servizio o dallo strumento di gestione.
  3. Passare questi valori insieme alla stringa FriendlyNameText a RequestVirtualSmartCardCreationAsync.
var pinPolicy = new SmartCardPinPolicy
    {
        MinLength = 6
    };

IBuffer adminkey = CryptographicBuffer.GenerateRandom(24);

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

Dopo che RequestVirtualSmartCardCreationAsync ha restituito l'oggetto SmartCardProvisioning associato, viene effettuato il provisioning della smart card virtuale e pronto per l'uso.

Nota

Per creare una smart card virtuale usando un'app di Windows in pacchetto, l'utente che esegue l'app deve essere membro del gruppo administrators. Se l'utente non è membro del gruppo administrators, la creazione di smart card virtuali avrà esito negativo.

Gestire le sfide di autenticazione

Per eseguire l'autenticazione con smart card o smart card virtuali, l'app deve fornire il comportamento per completare i problemi tra i dati della chiave amministratore archiviati nella scheda e i dati delle chiavi di amministratore gestiti dal server di autenticazione o dallo strumento di gestione.

Il codice seguente illustra come supportare l'autenticazione tramite smart card per i servizi o la modifica dei dettagli della scheda fisica o virtuale. Se i dati generati usando la chiave di amministrazione nella scheda ("verifica") corrispondono ai dati della chiave di amministratore forniti dal server o dallo strumento di gestione ("adminkey"), l'autenticazione ha esito positivo.

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

Questo codice a cui viene fatto riferimento nel resto di questo argomento è stato esaminato come completare un'azione di autenticazione e come applicare le modifiche alle smart card e alle informazioni sulle smart card virtuali.

Verificare la risposta di autenticazione tramite smart card o smart card virtuale

Ora che è stata definita la logica per le sfide di autenticazione, è possibile comunicare con il lettore per accedere alla smart card o, in alternativa, accedere a una smart card virtuale per l'autenticazione.

  1. Per iniziare la verifica, chiamare GetChallengeContextAsync dall'oggetto SmartCardProvisioning associato alla smart card. Verrà generata un'istanza di SmartCardChallengeContext, che contiene il valore Challenge della scheda.
  2. Passare quindi il valore di verifica della scheda e la chiave di amministrazione fornita dal servizio o dallo strumento di gestione al ChallengeResponseAlgorithm definito nell'esempio precedente.
  3. VerifyResponseAsync restituirà true se l'autenticazione ha esito positivo.
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);

Modificare o reimpostare un PIN utente

Per modificare il PIN associato a una smart card:

  1. Accedere alla scheda e generare l'oggetto SmartCardProvisioning associato.
  2. Chiamare RequestPinChangeAsync per visualizzare un'interfaccia utente all'utente per completare questa operazione.
  3. Se il PIN è stato modificato correttamente, la chiamata restituirà true.
SmartCardProvisioning provisioning =
    await SmartCardProvisioning.FromSmartCardAsync(card);

bool result = await provisioning.RequestPinChangeAsync();

Per richiedere una reimpostazione del PIN:

  1. Chiamare RequestPinResetAsync per avviare l'operazione. Questa chiamata include un metodo SmartCardPinResetHandler che rappresenta la smart card e la richiesta di reimpostazione del pin.
  2. SmartCardPinResetHandler fornisce informazioni che il ChallengeResponseAlgorithm, sottoposto a wrapping in una chiamata SmartCardPinResetDeferral, usa per confrontare il valore di verifica della scheda e la chiave di amministrazione fornita dal servizio o dallo strumento di gestione per autenticare la richiesta.
  3. Se la richiesta di verifica ha esito positivo, la chiamata RequestPinResetAsync viene completata; restituendo true se il PIN è stato reimpostato correttamente.
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();
        }
    });
}

Rimuovere una smart card o una smart card virtuale

Quando una smart card fisica viene rimossa, viene generato un evento CardRemoved quando la scheda viene eliminata.

Associare la generazione di questo evento al lettore di schede con il metodo che definisce il comportamento dell'app sulla scheda o sulla rimozione del lettore come gestore eventi. Questo comportamento può essere semplicemente quello di fornire una notifica all'utente che la scheda è stata rimossa.

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

La rimozione di una smart card virtuale viene gestita a livello di codice recuperando prima la scheda e quindi chiamando RequestVirtualSmartCardDeletionAsync dall'oggetto SmartCardProvisioning restituito.

bool result = await SmartCardProvisioning
    .RequestVirtualSmartCardDeletionAsync(card);