I have a badge reader in my laptop and a smartcard badge.
Following this guide from Microsoft, I can get the reader and set its CardAdded event.
In the part about getting an authentication response, the guide mentions a rootPage that stores an already inserted card. Since I'm still learning this code, I don't have that yet. Also the article doesn't mention where to put this fragment:
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);
}
Since Reader_CardAdded event supplies what I need, I just put the code there and insert my badge to test it.
Note: Aside from getting the card from the args, the try/catch, and supposing the adminKey is the pin, the meat of it is copied directly from the guide.
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;
}
}
}
Upon inserting my badge, the Reader_CardAdded event fires no problem. But when it comes to this line:
using (SmartCardChallengeContext context = await provisioning.GetChallengeContextAsync())
An exception is thrown
Message: The system cannot find the file specified. (Exception from HRESULT: 0x80070002)
Source: System.Private.CoreLib
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at FEOD.UWP.FEODSmartCard.<Reader_CardAdded>d__5.MoveNext()
I didn't expect that at all since the guide makes no mention of a potential exception, let alone one about a missing file.
The guide uses this example. I downloaded that code and fixed Scenario1_ProvisionTMP.xaml.cs to use my actual reader and card instead of virtual ones. The sample then throws the same exception.
e.g. in Create_Click, I only made these modifications
//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);
Has anyone successfully implemented this functionality?
Create a new project using "Blank App (Universal Windows)"
Add a button to MainPage.xml and add a Click Event to it
In MainPage.xaml.cs add the following methods
public async Task CardAuth()
{
try
{
IBuffer adminkey = CryptographicBuffer.GenerateRandom(24);
//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);
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;
}
For the Button click event add this one line of code
private void Card_OnClick(object sender, RoutedEventArgs e)
{
Task.Run(async () => await CardAuth());
}
Add one class to the solution
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;
}
}
Put a break point in CardAuth()'s catch.
Run the app, press the button, see the exception caused by GetChallengeContextAsync:
"The system cannot find the file specified."
User contributions licensed under CC BY-SA 3.0