Windows 10上C#中的智能卡

问题描述

我的笔记本电脑中有徽章读取器和智能卡徽章。

根据Microsoft的本指南,我可以获取读者并设置其CardAdded事件。

在获得身份验证响应的部分中,该指南提到了存储已插入卡的rootPage。由于我仍在学习此代码,所以我还没有。此外,本文也没有提及将此片段放在何处:

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

由于Reader_CardAdded事件满足了我的需求,所以我只需要在其中放置代码并插入徽章即可对其进行测试。

注意:除了从args获取卡片外,还可以进行try / catch并假设adminKey是pin,它的内容也可以直接从指南中复制。

private async void Reader_CardAdded(Smartcardreader sender,CardAddedEventArgs args)
{
    bool verifyResult = false;
    SmartCard card = args.SmartCard;
    if (card != null)
    {
        try
        {
            SmartCardProvisioning provisioning = await SmartCardProvisioning.FromSmartCardAsync(card);
            using (SmartCardChallengeContext context = await provisioning.GetChallengeContextAsync())
            {
                IBuffer adminKey = new Windows.Storage.Streams.Buffer(pinText);

                IBuffer response = ChallengeResponseAlgorithm.CalculateResponse(context.Challenge,adminKey);

                verifyResult = await context.VerifyResponseAsync(response);
            }
        }
        catch (Exception e)
        {
            Console.WriteLine(e);
            throw;
        }
    }
}

插入徽章后,Reader_CardAdded事件不会引发任何问题。但是当涉及到这一行时:

using (SmartCardChallengeContext context = await provisioning.GetChallengeContextAsync())

引发异常

消息:系统找不到指定的文件。 (HRESULT的异常:0x80070002)
来源:System.Private.CoreLib

在System.Runtime.ExceptionServices.ExceptiondispatchInfo.Throw()
在System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务任务)
在System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务任务)
在System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
在FEOD.UWP.FEODSmartCard中。 d__5.MoveNext()

我完全没想到,因为指南没有提到潜在的异常,更不用说关于丢失文件的情况了。

指南使用此example。我下载了该代码,并修复了Scenario1_ProvisionTMP.xaml.cs,以使用实际的读取器和卡而不是虚拟的读取器和卡。然后该示例将引发相同的异常。

例如在Create_Click中,我仅进行了这些修改

//SmartCardPinPolicy pinPolicy = ParsePinPolicy();
            
IBuffer adminkey = CryptographicBuffer.Generaterandom(MainPage.ADMIN_KEY_LENGTH_IN_BYTES);

//SmartCardProvisioning provisioning = await SmartCardProvisioning.RequestVirtualSmartCardCreationAsync(FriendlyName.Text,adminkey,pinPolicy);

string selector = Smartcardreader.GetDeviceSelector();
DeviceinformationCollection devices = await Deviceinformation.FindAllAsync(selector);

Deviceinformation device = devices[0];
Smartcardreader reader = await Smartcardreader.FromIdAsync(device.Id);
SmartCard card = reader.FindAllCardsAsync().GetResults().First();

SmartCardProvisioning provisioning = await SmartCardProvisioning.FromSmartCardAsync(card);

有人成功实现了此功能吗?


----------------- SIMPLE REPRO ---------------------------

  1. 使用“空白应用程序(通用Windows)”创建一个新项目

  2. 向MainPage.xml添加按钮,并向其中添加Click事件

  3. 在MainPage.xaml.cs中添加以下方法

     public async Task CardAuth()
     {
         try
         {
    
             IBuffer adminkey = CryptographicBuffer.Generaterandom(24);
    
             //SmartCardProvisioning provisioning = await SmartCardProvisioning.RequestVirtualSmartCardCreationAsync(FriendlyName.Text,pinPolicy);
    
             string selector = Smartcardreader.GetDeviceSelector();
             DeviceinformationCollection devices = await Deviceinformation.FindAllAsync(selector);
    
             Deviceinformation device = devices[0];
             Smartcardreader reader = await Smartcardreader.FromIdAsync(device.Id);
             SmartCard card = reader.FindAllCardsAsync().GetResults().First();
    
             SmartCardProvisioning provisioning = await SmartCardProvisioning.FromSmartCardAsync(card);
    
             reader.CardAdded += Reader_CardAdded;
    
             using (var context = await provisioning.GetChallengeContextAsync())
             {
                 IBuffer response = ChallengeResponseAlgorithm.CalculateResponse(context.Challenge,adminkey);
                 await context.ProvisionAsync(response,true);
             }
    
         }
         catch (Exception e)
         {
             Console.WriteLine(e);
         }
     }
    
     private void Reader_CardAdded(Smartcardreader sender,CardAddedEventArgs args)
     {
         var a = 1;
     }
    
  4. 对于Button click事件,添加以下一行代码

     private void Card_OnClick(object sender,RoutedEventArgs e)
     {
         Task.Run(async () => await CardAuth());
     }
    
  5. 解决方案中添加一类

     static class ChallengeResponseAlgorithm
     {
         /// <summary>
         /// Calculates the response by encrypting the challenge by using Triple DES (3DES).
         /// If the resulting values are the same,the authentication is successful.
         /// </summary>
         /// <param name="challenge">a block of challenge data generated by smart card using its admin key</param>
         /// <param name="adminkey">the admin key of the smart card,which is normally saved on the server side or management tool.</param>
         /// <returns>the response</returns>
         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;
         }
     }
    
  6. 在CardAuth()的捕获中放入一个断点。

  7. 运行应用程序,按下按钮,查看由GetChallengeContextAsync引起的异常:

“系统找不到指定的文件。”

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)