Смарт-карты

В этом разделе объясняется, как приложения Windows могут использовать смарт-карты для подключения пользователей к защищенным сетевым службам, включая доступ к физическим средствам чтения смарт-карт, создание виртуальных смарт-карт, взаимодействие с смарт-картами, проверку подлинности пользователей, сброс пин-кодов пользователей и удаление или отключение смарт-карт.

API-интерфейсы среда выполнения Windows (WinRT) для смарт-карт являются частью пакета SDK для Windows. Эти API были созданы для использования в приложениях универсальная платформа Windows (UWP), но они также могут использоваться в приложениях WinUI или в упакованных классических приложениях, включая WPF и Windows Forms. Дополнительные сведения об использовании API WinRT в классическом приложении Windows см. в статье "Вызов API среда выполнения Windows" в классических приложениях.

Настройка манифеста приложения

Прежде чем приложение сможет пройти проверку подлинности пользователей с помощью смарт-карт или виртуальных смарт-карт, необходимо задать возможность общих сертификатов пользователей в файле project Package.appxmanifest проекта WinUI или проекта упаковки.

Доступ к подключенным средствам чтения карт и смарт-картам

Вы можете запросить средства чтения и подключенные смарт-карты, передав идентификатор устройства (указанный в DeviceInformation) методу SmartCardReader.FromIdAsync . Чтобы получить доступ к смарт-картам, подключенным к возвращенному устройству чтения, вызовите 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();
}

Вы также должны включить приложение для отслеживания событий CardAdded , реализуя метод обработки поведения приложения при вставке карточки.

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

Затем вы можете передать каждый возвращенный объект SmartCard в SmartCardProvisioning, чтобы получить доступ к методам, которые позволяют приложению получать доступ к конфигурации и настраивать ее конфигурацию.

Создание виртуальной смарт-карты

Чтобы создать виртуальную смарт-карту с помощью SmartCardProvisioning, приложению сначала потребуется указать понятное имя, ключ администратора и SmartCardPinPolicy. Понятное имя обычно предоставляется приложению, но приложению по-прежнему потребуется предоставить ключ администратора и создать экземпляр текущего SmartCardPinPolicy , прежде чем передавать все три значения в RequestVirtualSmartCardCreationAsync.

  1. Создание нового экземпляра SmartCardPinPolicy
  2. Создайте значение ключа администратора, вызвав CryptographicBuffer.GenerateRandom в значении ключа администратора, предоставленном службой или средством управления.
  3. Передайте эти значения вместе со строкой FriendlyNameText в RequestVirtualSmartCardCreationAsync.
var pinPolicy = new SmartCardPinPolicy
    {
        MinLength = 6
    };

IBuffer adminkey = CryptographicBuffer.GenerateRandom(24);

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

После того как RequestVirtualSmartCardCreationAsync вернул связанный объект SmartCardProvisioning , виртуальная смарт-карта подготовлена и готова к использованию.

Примечание.

Чтобы создать виртуальную смарт-карту с помощью упаковаемого приложения Windows, пользователь, на котором запущено приложение, должен быть членом группы администраторов. Если пользователь не является членом группы администраторов, создание виртуальной смарт-карты завершится ошибкой.

Обработка проблем проверки подлинности

Для проверки подлинности с помощью смарт-карт или виртуальных смарт-карт приложение должно обеспечить поведение для выполнения проблем между данными ключа администратора, хранящимися на карточке, и данными ключа администратора, которые хранятся сервером проверки подлинности или средством управления.

В следующем коде показано, как поддерживать проверку подлинности смарт-карты для служб или изменения физических или виртуальных карточек. Если данные, созданные с помощью ключа администратора на карточке ("вызов"), совпадают с данными ключа администратора, предоставленными сервером или средством управления ("adminkey"), проверка подлинности выполнена успешно.

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

Вы увидите этот код, на который ссылается на оставшуюся часть этого раздела, мы рассмотрим, как выполнить действие проверки подлинности и как применить изменения к данным смарт-карты и виртуальной смарт-карты.

Проверка ответа на проверку подлинности смарт-карт или виртуальной смарт-карты

Теперь, когда у нас есть логика для задач проверки подлинности, мы можем взаимодействовать с читателем, чтобы получить доступ к смарт-карте или также получить доступ к виртуальной смарт-карте для проверки подлинности.

  1. Чтобы начать задачу, вызовите GetChallengeContextAsync из объекта SmartCardProvisioning , связанного с смарт-картой. Это приведет к созданию экземпляра SmartCardChallengeContext, который содержит значение вызова карточки.
  2. Затем передайте значение вызова карточки и ключ администратора, предоставленный службой или средством управления, в объект ChallengeResponseAlgorithm , определенный в предыдущем примере.
  3. VerifyResponseAsync вернет значение true , если проверка подлинности выполнена успешно.
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);

Изменение или сброс ПИН-кода пользователя

Чтобы изменить ПИН-код, связанный с смарт-картой, выполните следующие действия.

  1. Откройте карточку и создайте связанный объект SmartCardProvisioning .
  2. Вызовите RequestPinChangeAsync , чтобы отобразить пользовательский интерфейс пользователю для выполнения этой операции.
  3. Если ПИН-код был успешно изменен, вызов вернет значение true.
SmartCardProvisioning provisioning =
    await SmartCardProvisioning.FromSmartCardAsync(card);

bool result = await provisioning.RequestPinChangeAsync();

Чтобы запросить сброс ПИН-кода:

  1. Вызовите RequestPinResetAsync , чтобы инициировать операцию. Этот вызов включает метод SmartCardPinResetHandler , представляющий смарт-карту и запрос сброса пин-кода.
  2. SmartCardPinResetHandler предоставляет сведения о том, что наш вызов ChallengeResponseAlgorithm, упакованный в вызов SmartCardPinResetDeferral , используется для сравнения значения проблемы карты и ключа администратора, предоставленного службой или средством управления для проверки подлинности запроса.
  3. Если проблема выполнена успешно, вызов RequestPinResetAsync завершается; возвращает значение true, если ПИН-код был успешно сброшен.
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();
        }
    });
}

Удаление смарт-карты или виртуальной смарт-карты

При удалении физической смарт-карты событие "Удалена карточка" будет возникать при удалении карточки.

Свяжите запуск этого события с средством чтения карт с методом, определяющим поведение приложения на карточке или средстве чтения в качестве обработчика событий. Это может быть что-то простое, как предоставление пользователю уведомления о том, что карточка была удалена.

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

Удаление виртуальной смарт-карты выполняется программным способом путем получения карточки, а затем вызова RequestVirtualSmartCardDeletionAsync из возвращаемого объекта SmartCardProvisioning.

bool result = await SmartCardProvisioning
    .RequestVirtualSmartCardDeletionAsync(card);