Partager via


Cartes à puce

Cette rubrique explique comment les applications Windows peuvent utiliser des cartes à puce pour connecter des utilisateurs à des services réseau sécurisés, notamment comment accéder aux lecteurs de cartes à puce physiques, créer des cartes à puce virtuelles, communiquer avec des cartes à puce, authentifier les utilisateurs, réinitialiser les codes CONFIDENTIEL utilisateur et supprimer ou déconnecter des cartes à puce.

Les API Windows Runtime (WinRT) pour les cartes à puce font partie du Kit de développement logiciel (SDK) Windows. Ces API ont été créées pour une utilisation dans des applications plateforme Windows universelle (UWP), mais elles peuvent également être utilisées dans des applications WinUI ou dans des applications de bureau empaquetées, notamment WPF et Windows Forms. Pour plus d’informations sur l’utilisation des API WinRT dans votre application de bureau Windows, consultez Appeler les API Windows Runtime dans les applications de bureau.

Configurer le manifeste de l’application

Pour que votre application puisse authentifier les utilisateurs à l’aide de cartes à puce ou de cartes à puce virtuelles, vous devez définir la fonctionnalité Certificats utilisateur partagés dans le fichier Project Package.appxmanifest de votre projet WinUI ou projet d’empaquetage.

Accéder aux lecteurs de cartes connectées et aux cartes à puce

Vous pouvez rechercher des lecteurs et des cartes à puce jointes en passant l’ID d’appareil (spécifié dans DeviceInformation) à la méthode SmartCardReader.FromIdAsync . Pour accéder aux cartes à puce actuellement attachées à l’appareil lecteur retourné, appelez 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();
}

Vous devez également permettre à votre application d’observer les événements CardAdded en implémentant une méthode pour gérer le comportement de l’application lors de l’insertion de carte.

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

Vous pouvez ensuite transmettre chaque objet SmartCard retourné à SmartCardProvisioning pour accéder aux méthodes qui permettent à votre application d’accéder à votre application et de personnaliser sa configuration.

Créer une carte à puce virtuelle

Pour créer une carte à puce virtuelle à l’aide de SmartCardProvisioning, votre application doit d’abord fournir un nom convivial, une clé d’administration et une SmartCardPinPolicy. Le nom convivial est généralement fourni à l’application, mais votre application doit toujours fournir une clé d’administration et générer une instance de la smartCardPinPolicy actuelle avant de passer les trois valeurs à RequestVirtualSmartCardCreationAsync.

  1. Créer une instance d’un SmartCardPinPolicy
  2. Générez la valeur de la clé d’administration en appelant CryptographicBuffer.GenerateRandom sur la valeur de clé d’administration fournie par le service ou l’outil de gestion.
  3. Transmettez ces valeurs avec la chaîne FriendlyNameText à RequestVirtualSmartCardCreationAsync.
var pinPolicy = new SmartCardPinPolicy
    {
        MinLength = 6
    };

IBuffer adminkey = CryptographicBuffer.GenerateRandom(24);

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

Une fois RequestVirtualSmartCardCreationAsync retourné l’objet SmartCardProvisioning associé, la carte à puce virtuelle est provisionnée et prête à être utilisée.

Remarque

Pour créer une carte à puce virtuelle à l’aide d’une application Windows empaquetée, l’utilisateur exécutant l’application doit être membre du groupe administrateurs. Si l’utilisateur n’est pas membre du groupe Administrateurs, la création de carte à puce virtuelle échoue.

Gérer les défis liés à l’authentification

Pour vous authentifier avec des cartes à puce ou des cartes à puce virtuelles, votre application doit fournir le comportement permettant d’effectuer des défis entre les données de clé d’administration stockées sur la carte et les données de clé d’administration conservées par le serveur d’authentification ou l’outil de gestion.

Obtention de la clé d’administration

Avant de pouvoir effectuer l’authentification, vous devez obtenir la clé d’administration. La source de la clé d’administration dépend de votre scénario :

  • Pour les cartes à puce virtuelles que vous avez créées : utilisez la même clé d’administration générée lors de la création de la carte (comme indiqué dans la section « Créer une carte à puce virtuelle » ci-dessus). Vous devez stocker cette clé de manière sécurisée pour une utilisation ultérieure de l’authentification.
  • Pour les cartes à puce physiques ou virtuelles existantes : la clé d’administration est généralement fournie par le service informatique de votre organisation, le système de gestion des cartes ou le service qui a émis la carte.
  • Pour le développement/test : vous pouvez générer une clé d’administration de test à l’aide de CryptographicBuffer.GenerateRandom , comme indiqué dans l’exemple de création de carte virtuelle ci-dessous.
// 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);

Exemples de méthodes de gestion des clés d’administration

Voici des exemples de méthodes que vous pouvez implémenter pour stocker et récupérer en toute sécurité les clés d’administration :

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

Algorithme d’authentification

Le code suivant montre comment prendre en charge l’authentification par carte à puce pour les services ou la modification des détails de carte physique ou virtuelle. Si les données générées à l’aide de la clé d’administration sur la carte (« défi ») sont identiques aux données de clé d’administration fournies par le serveur ou l’outil de gestion (« adminkey »), l’authentification réussit.

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

Vous verrez ce code référencé tout au long du reste de cette rubrique, nous avons examiné comment effectuer une action d’authentification et comment appliquer des modifications aux informations de carte à puce et de carte à puce virtuelle.

Vérifier la réponse d’authentification de carte à puce ou de carte à puce virtuelle

Maintenant que nous avons la logique pour les défis d’authentification définis, nous pouvons communiquer avec le lecteur pour accéder à la carte à puce, ou autrement, accéder à une carte à puce virtuelle pour l’authentification.

  1. Pour commencer le défi, appelez GetChallengeContextAsync à partir de l’objet SmartCardProvisioning associé à la carte à puce. Cela génère une instance de SmartCardChallengeContext qui contient la valeur Challenge de la carte.
  2. Ensuite, passez la valeur de défi de la carte et la clé d’administration fournie par le service ou l’outil de gestion au ChallengeResponseAlgorithm que nous avons défini dans l’exemple précédent.
  3. VerifyResponseAsync retourne true si l’authentification réussit.
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);

Modifier ou réinitialiser un code confidentiel utilisateur

Pour modifier le code confidentiel associé à une carte à puce :

  1. Accédez à la carte et générez l’objet SmartCardProvisioning associé.
  2. Appelez RequestPinChangeAsync pour afficher une interface utilisateur à l’utilisateur pour terminer cette opération.
  3. Si le code confidentiel a été correctement modifié, l’appel retourne true.
SmartCardProvisioning provisioning =
    await SmartCardProvisioning.FromSmartCardAsync(card);

bool result = await provisioning.RequestPinChangeAsync();

Pour demander une réinitialisation de code confidentiel :

  1. Appelez RequestPinResetAsync pour lancer l’opération. Cet appel inclut une méthode SmartCardPinResetHandler qui représente la carte à puce et la demande de réinitialisation d’épingle.
  2. SmartCardPinResetHandler fournit des informations que notre ChallengeResponseAlgorithm, encapsulé dans un appel SmartCardPinResetDeferral , utilise pour comparer la valeur de défi de la carte et la clé d’administration fournie par le service ou l’outil de gestion pour authentifier la demande.
  3. Si le défi réussit, l’appel RequestPinResetAsync est terminé ; retourne true si le code confidentiel a été réinitialisé.
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();
        }
    });
}

Supprimer une carte à puce ou une carte à puce virtuelle

Lorsqu’une carte à puce physique est supprimée, un événement CardRemoved se déclenche lorsque la carte est supprimée.

Associez le déclenchement de cet événement au lecteur de carte à la méthode qui définit le comportement de votre application sur la suppression de carte ou de lecteur en tant que gestionnaire d’événements. Ce comportement peut être quelque chose aussi simplement que de fournir une notification à l’utilisateur que la carte a été supprimée.

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

La suppression d’une carte à puce virtuelle est gérée par programme en récupérant d’abord la carte, puis en appelant RequestVirtualSmartCardDeletionAsync à partir de l’objet retourné SmartCardProvisioning .

bool result = await SmartCardProvisioning
    .RequestVirtualSmartCardDeletionAsync(card);