Мне нужно написать некоторые функции UWP, которые могут аутентифицировать пользователя с виртуальной смарт-карты TPM. В идеале я хотел бы использовать всплывающее окно, подобное тому, которое появляется в браузере, которое просит вас выбрать сертификат, а затем запрашивает пин-код, если он привязан к смарт-карте, как показано ниже.
У меня есть следующий код из сообщения, найденного здесь: Вход пользователя с Смарт-карта для приложения Windows UWP, но у меня возникает та же проблема при попытке подписать «Поставщик не может выполнить действие, так как контекст был получен как беззвучный».
ReadOnlyList<Certificate> Certs;
CertificateQuery CertQuery = new CertificateQuery();
CertQuery.HardwareOnly = true;
Certs = await CertificateStores.FindAllAsync(CertQuery);
string strEncrypt = "test";
IBuffer BufferToEncrypt = CryptographicBuffer.ConvertStringToBinary(strEncrypt, BinaryStringEncoding.Utf8);
foreach (Certificate Cert in Certs)
{
Debug.WriteLine($"Cert: {Cert.Subject}");
Debug.WriteLine($"Storagename: {Cert.KeyStorageProviderName}");
if (Cert.HasPrivateKey && ((Cert.KeyStorageProviderName == "Microsoft Base Smart Card Crypto Provider") || Cert.KeyStorageProviderName == "Microsoft Smart Card Key Storage Provider"))
{
CryptographicKey Key = null;
try
{
Key = await PersistedKeyProvider.OpenKeyPairFromCertificateAsync(Cert, HashAlgorithmNames.Sha1, CryptographicPadding.RsaPkcs1V15);
Debug.WriteLine("Got keypair");
}
catch (Exception ex)
{
// Could not open Smart Card Key Pair
Debug.WriteLine("Could not open Smart Card Key Pair");
}
if (Key != null)
{
try
{
// Try to Sign with Cert Private key
IBuffer EncryptedBuffer = CryptographicEngine.Sign(Key, BufferToEncrypt);
Debug.WriteLine("Signing successful");
}
catch (Exception ex)
{
// Could not sign
Debug.WriteLine("Could not sign");
Debug.WriteLine($"Error: {ex.Message}");
}
}
}
}
Есть ли способ создать такое же всплывающее окно? Должен ли я построить его сам? Если нет, если я выбираю сертификат программно, как я могу запросить пин-код и проверить его?
Я ищу функциональность, показанную выше, которая также похожа на KeyChain.ChoosePrivateKeyAlias и IKeyChainAliasCallback, которые существуют в Android и позволяют пользователю выбрать сертификат, если кто-то также знаком с этим.
Изменить 1
Изменение строки:
IBuffer EncryptedBuffer = await CryptographicEngine.Sign(Key, BufferToEncrypt);
to
IBuffer EncryptedBuffer = await CryptographicEngine.SignAsync(Key, BufferToEncrypt);
предлагает мне ввести булавку, но мне все еще нужно выяснить всплывающее окно для выбора сертификата по сравнению с программным выбором.
Редактировать 2 Вы можете отобразить окно «Выбор сертификата», используя
CredentialPickerOptions options = new CredentialPickerOptions();
options.AuthenticationProtocol = AuthenticationProtocol.Ntlm;
options.Message = "Please select your certificate";
options.Caption = "Select a Certificate";
options.TargetName = ".";
options.CredentialSaveOption = CredentialSaveOption.Hidden;
CredentialPickerResults credentialsPicked = await
CredentialPicker.PickAsync(options);
Однако в CredentialPickerResults есть поле Credential типа IBuffer. Я не понимаю, что я должен делать с этим, чтобы либо получить сертификат напрямую, либо использовать его для поиска в хранилище сертификатов, чтобы получить выбранный сертификат.