다음을 통해 공유


스마트 카드

이 항목에서는 Windows 앱이 스마트 카드를 사용하여 물리적 스마트 카드 판독기 액세스, 가상 스마트 카드 만들기, 스마트 카드와 통신, 사용자 인증, 사용자 PIN 재설정, 스마트 카드 제거 또는 연결 끊기 등의 네트워크 서비스에 사용자를 연결하는 방법을 설명합니다.

스마트 카드용 WinRT(Windows 런타임) API는 Windows SDK(소프트웨어 개발 키트)일부입니다. 이러한 API는 UWP(유니버설 Windows 플랫폼) 앱에서 사용하기 위해 만들어졌지만 WinUI 앱 또는 WPF 및 Windows Forms를 비롯한 패키지 데스크톱 앱에서도 사용할 수 있습니다. Windows 데스크톱 앱에서 WinRT API를 사용하는 방법에 대한 자세한 내용은 데스크톱 앱에서 Windows 런타임 API 호출을 참조하세요.

앱 매니페스트 구성

앱이 스마트 카드 또는 가상 스마트 카드를 사용하여 사용자를 인증하려면 먼저 WinUI 프로젝트 또는 패키징 프로젝트의 Project Package.appxmanifest 파일에서 공유 사용자 인증서 기능을 설정해야 합니다.

연결된 카드 리더기 및 스마트 카드에 엑세스 하세요

DeviceInformation에서 지정된 디바이스 ID를 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 인스턴스를 생성하고 관리 키를 제공한 후 3개 모든 값을 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인스턴스가 생성되며, 이는 카드의 Challenge 값을 포함합니다.
  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);

사용자 PIN 변경 혹은 재설정

스마트 카드와 연관된 PIN을 변경하려면 다음을 수행합니다:

  1. 카드에 엑세스하여 연관된 SmartCardProvisioning 오브젝트를 생성합니다.
  2. RequestPinChangeAsync를 호출하여 사용자에게 UI를 표시하는 것으로 이 작업을 완료합니다.
  3. PIN이 성공적으로 변경되었을 경우 호출은 을 도출합니다.
SmartCardProvisioning provisioning =
    await SmartCardProvisioning.FromSmartCardAsync(card);

bool result = await provisioning.RequestPinChangeAsync();

PIN 재설정을 요청하려면 다음을 수행하세요:

  1. RequestPinResetAsync를 호출하는 것으로 작업을 시작합니다. 이 호출에는 스마트 카드와 PIN 재설정 요청을 구현하는 SmartCardPinResetHandler 메서드가 포함되어 있습니다.
  2. SmartCardPinResetHandlerSmartCardPinResetDeferral 호출에 래핑된 ChallengeResponseAlgorithm에서 요청을 인증하기 위해 카드의 질문 값과 서비스 또는 관리 도구에서 제공한 관리자 키를 비교하는 데 사용되는 정보를 제공합니다.
  3. 시도가 성공적이였다면 RequestPinResetAsync 호출이 완료되고; PIN이 성공적으로 재설정 되었다면 을 출력합니다.
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();
        }
    });
}

스마트 카드 또는 가상 스마트 카드 제거하기

실제 스마트 카드가 제거되면 카드가 삭제될 때 CardRemoved 이벤트가 발생합니다.

이 이벤트의 발생을 카드 리더기와 카드 또는 리더기 제거 시 앱의 동작을 이벤트 처리기로 정의하는 메서드와 연관짓습니다. 이 동작은 사용자에게 카드가 제거되었다는 알림을 제공하는 것과 같은 단순한 것일 수 있습니다.

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

가상 스마트 카드 제거는 프로그래밍 방식으로 처리되며 먼저 카드를 수습하는 것으로 시작합니다. RequestVirtualSmartCardDeletionAsync를 호출하는 것이 다음 단계이며 이 호출은 SmartCardProvisioning 출력 오브잭트에서 호출됩니다.

bool result = await SmartCardProvisioning
    .RequestVirtualSmartCardDeletionAsync(card);