Tarjetas inteligentes

En este tema se explica la manera en que las aplicaciones para la Plataforma universal de Windows (UWP) pueden usar tarjetas inteligentes para conectar a los usuarios para proteger los servicios de red, incluido cómo obtener acceso a los lectores de tarjetas inteligentes físicas, crear tarjetas inteligentes virtuales, comunicarse con tarjetas inteligentes, autenticar usuarios, restablecer los PIN de usuario y quitar o desconectar tarjetas inteligentes.

Configuración del manifiesto de la aplicación

Para que la aplicación pueda autenticar los usuarios mediante tarjetas inteligentes o tarjetas inteligentes virtuales, debes establecer la funcionalidad Certificados de usuario compartidos en el archivo Package.appxmanifest.

Acceder a lectores de tarjetas conectados y tarjetas inteligentes

Para consultar lectores y tarjetas inteligentes conectadas deberás pasar el identificador del dispositivo (especificado en DeviceInformation) al método SmartCardReader.FromIdAsync. Para acceder a las tarjetas inteligentes conectadas al dispositivo lector devuelto, llama a 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();
}

También deberás habilitar la aplicación para que busque eventos CardAdded mediante una función que determine el comportamiento de la aplicación cuando se inserte una tarjeta.

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

Después, puedes pasar cada objeto SmartCard devuelto a SmartCardProvisioning para acceder a los métodos que permiten que tu aplicación acceda a su configuración y la personalice.

Crear una tarjeta inteligente virtual

Para crear una tarjeta inteligente virtual usando SmartCardProvisioning, tu aplicación primero debe proporcionar un nombre descriptivo, una clave de administración y una SmartCardPinPolicy. Por lo general, el nombre descriptivo es algo que se proporciona a la aplicación, pero esta debe proporcionar también una clave de administración y generar una instancia de la SmartCardPinPolicy actual antes de pasar los tres valores a RequestVirtualSmartCardCreationAsync.

  1. Crea una nueva instancia de una clase SmartCardPinPolicy.
  2. Para generar el valor de clave de administración, llama a CryptographicBuffer.GenerateRandom mediante el valor de clave de administración proporcionado por el servicio o por la herramienta de administración.
  3. Pasa estos valores junto con la cadena FriendlyNameText a RequestVirtualSmartCardCreationAsync.
SmartCardPinPolicy pinPolicy = new SmartCardPinPolicy();
pinPolicy.MinLength = 6;

IBuffer adminkey = CryptographicBuffer.GenerateRandom(24);

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

Después de que el método RequestVirtualSmartCardCreationAsync haya devuelto el objeto SmartCardProvisioning asociado, la tarjeta inteligente virtual está aprovisionada y lista para usar.

Nota:

Para crear una tarjeta inteligente virtual mediante una aplicación para UWP, el usuario que ejecuta la aplicación debe ser miembro del grupo de administradores. Si el usuario no es miembro del grupo de administradores, se producirá un error en la creación de tarjetas inteligentes virtuales.

Administrar los desafíos de autenticación

Para autenticar con tarjetas inteligentes o tarjetas inteligentes virtuales, tu aplicación debe proporcionar el comportamiento para completar los desafíos entre los datos de la clave de administración almacenados en la tarjeta y los datos de la clave de administración que mantiene el servidor de autenticación o la herramienta de administración.

El código siguiente muestra cómo admitir la autenticación con tarjeta inteligente para los servicios o cómo modificar los detalles de una tarjeta física o virtual. Si los datos generados con la clave de administración en la tarjeta ("desafío") son los mismos que los datos de la clave de administración proporcionados por el servidor o por la herramienta de administración ("adminkey"), la autenticación es correcta.

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

Verás que hacemos referencia a este código en el resto del tema; en él revisamos cómo completar una acción de autenticación y cómo aplicar cambios a la información de una tarjeta inteligente o una tarjeta inteligente virtual.

Comprobar la respuesta de la autenticación con tarjeta inteligente o con tarjeta inteligente virtual

Ahora que tenemos definida la lógica de los desafíos de autenticación, podemos comunicarnos con el lector para acceder a la tarjeta inteligente, o bien, acceder a una tarjeta inteligente virtual para la autenticación.

  1. Para comenzar el desafío, llama a GetChallengeContextAsync desde el objeto SmartCardProvisioning asociado con la tarjeta inteligente. Esto generará una instancia de SmartCardChallengeContext, que contiene el valor de Desafío de la tarjeta.

  2. A continuación, pasa el valor del desafío de la tarjeta y la clave de administración proporcionada por el servicio o por la herramienta de administración al ChallengeResponseAlgorithm que hemos definido en el ejemplo anterior.

  3. VerifyResponseAsync devolverá true si la autenticación es correcta.

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

Cambiar o restablecer un PIN de usuario

Para cambiar el PIN asociado a una tarjeta inteligente:

  1. Accede a la tarjeta y genera el objeto SmartCardProvisioning asociado.
  2. Llama a RequestPinChangeAsync para mostrar al usuario una interfaz de usuario para que complete esta operación.
  3. Si el PIN se cambió correctamente, la llamada devolverá true.
SmartCardProvisioning provisioning =
    await SmartCardProvisioning.FromSmartCardAsync(card);

bool result = await provisioning.RequestPinChangeAsync();

Solicitar el restablecimiento de un PIN:

  1. Llama a RequestPinResetAsync para iniciar la operación. Esta llamada incluye un método SmartCardPinResetHandler que representa la tarjeta inteligente y la solicitud de restablecimiento del PIN.

  2. SmartCardPinResetHandler proporciona información que nuestro elemento ChallengeResponseAlgorithm, encapsulado en una llamada a SmartCardPinResetDeferral usa para comparar el valor del desafío de la tarjeta con la clave de administración proporcionada por el servicio o por la herramienta de administración con el fin de autenticar la solicitud.

  3. Si el desafío es correcto, la llamada a RequestPinResetAsync finaliza y devuelve true si el PIN se restableció correctamente.

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

Quitar una tarjeta inteligente o una tarjeta inteligente virtual

Cuando se quita una tarjeta inteligente física, se activa un evento CardRemoved cuando la tarjeta se elimina.

Asocia la activación de este evento con el lector de tarjetas usando el método que define el comportamiento de tu aplicación al quitar la tarjeta o el lector como un controlador de eventos. Este comportamiento puede ser tan simple como proporcionar una notificación al usuario cuando se retira la tarjeta.

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

La retirada de una tarjeta inteligente virtual se controla mediante programación; para ello, se recupera primero la tarjeta y, después, se llama a RequestVirtualSmartCardDeletionAsync desde el objeto SmartCardProvisioning devuelto.

bool result = await SmartCardProvisioning
    .RequestVirtualSmartCardDeletionAsync(card);