智慧卡
本主題說明 Windows 應用程式如何使用智慧卡將用戶連線到安全的網路服務,包括如何存取實體智慧卡讀取器、建立虛擬智慧卡、與智慧卡通訊、驗證使用者、重設使用者 PIN,以及移除或中斷智慧卡的連線。
智慧卡 Windows 執行階段 (WinRT) API 是 Windows 軟體開發工具包 (SDK) 的一部分。 這些 API 已建立以用於 通用 Windows 平台 (UWP) 應用程式中,但也可以在 WinUI 應用程式或封裝的桌面應用程式中使用,包括 WPF 和 Windows Forms。 如需在 Windows 傳統型應用程式中使用 WinRT API 的詳細資訊,請參閱在傳統型應用程式中呼叫 Windows 執行階段 API。
設定應用程式資訊清單
您必須先在 WinUI 專案或封裝專案的 Package.appxmanifest 檔案中設定 共用用戶憑證 功能,您的應用程式才能使用智慧卡或虛擬智慧卡來驗證使用者。
存取連接的讀卡機和智慧卡
您可以透過將裝置識別碼 (在 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。
- 建立 SmartCardPinPolicy 的新執行個體
- 透過對服務或管理工具提供的管理金鑰值呼叫 CryptographicBuffer.GenerateRandom 來產生管理金鑰值。
- 將這些值與 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 應用程式建立虛擬智慧卡,執行應用程式的使用者必須是系統管理員群組的成員。 如果使用者不是管理員群組的成員,虛擬智慧卡建立將會失敗。
處理驗證質詢
若要使用智慧卡或虛擬智慧卡進行驗證,您的應用程式必須提供完成卡片上儲存的管理密鑰資料,與驗證伺服器或管理工具維護的管理密鑰資料之間的質詢行為。
以下程式碼顯示如何支援服務的智慧卡驗證或實體或虛擬卡詳細資訊的修改。 如果使用卡片上的管理金鑰產生的資料 (「challenge」) 與伺服器或管理工具提供的管理金鑰資料 (「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;
}
}
您將在本主題的其餘部分看到此程式碼,我們將回顧如何完成驗證動作,以及如何將變更套用於智慧卡和虛擬智慧卡資訊。
驗證智慧卡或虛擬智慧卡驗證回應
現在我們已經定義了驗證質詢的邏輯,我們可以與讀卡機通訊以存取智慧卡,或存取虛擬智慧卡進行驗證。
- 若要開始質詢,請從與智慧卡關聯的 SmartCardProvisioning 物件呼叫 GetChallengeContextAsync。 這將產生 SmartCardChallengeContext 的執行個體,其中包含卡片的質詢值。
- 接下來,將卡片的質詢值和服務或管理工具提供的管理金鑰,傳遞給我們在上一個範例中定義的 ChallengeResponseAlgorithm。
- 如果驗證成功,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:
- 存取卡片並產生關聯的 SmartCardProvisioning 物件。
- 呼叫 RequestPinChangeAsync 向使用者顯示 UI 以完成此作業。
- 如果 PIN 成功變更,呼叫會傳回 True。
SmartCardProvisioning provisioning =
await SmartCardProvisioning.FromSmartCardAsync(card);
bool result = await provisioning.RequestPinChangeAsync();
若要要求 PIN 重設:
- 呼叫 RequestPinResetAsync 以啟動作業。 此呼叫包括代表智慧卡和釘選重設請求的 SmartCardPinResetHandler 方法。
- SmartCardPinResetHandler 提供了封裝在 SmartCardPinResetDeferral 呼叫中的 ChallengeResponseAlgorithm 所提供的資訊,用於將卡片的質詢值與服務或管理工具提供的管理金鑰進行比較,以驗證請求。
- 如果質詢成功,則 RequestPinResetAsync 呼叫完成; 如果 PIN 碼重設成功,則傳回 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();
}
});
}
移除智慧卡或虛擬智慧卡
當實體智慧卡移除時,CardRemoved 事件將在該卡片刪除時觸發。
將此事件的觸發與讀卡機關聯,並使用將卡片或讀卡機移除時應用程式的行為定義為事件處理常式的方法。 此行為就像通知使用者卡片已移除一樣簡單。
reader = card.Reader;
reader.CardRemoved += HandleCardRemoved;
透過先擷取卡片,然後從 SmartCardProvisioning 傳回的物件呼叫 RequestVirtualSmartCardDeletionAsync,以程式設計方式處理虛擬智慧卡的移除。
bool result = await SmartCardProvisioning
.RequestVirtualSmartCardDeletionAsync(card);