Мне нужно написать некоторые функции UWP, которые могут аутентифицировать пользователя с виртуальной смарт-карты TPM.В идеале я хотел бы использовать всплывающее окно, подобное тому, которое появляется в браузере, которое просит вас выбрать сертификат, а затем запрашивает PIN-код, если он привязан к смарт-карте, как показано ниже.
У меня есть следующий код из сообщения, найденного здесь: Логин пользователя с приложением UWP для смарт-карт для Windows , но у меня возникла та же проблема при попыткезнак «Провайдер не может выполнить действие, поскольку контекст был получен как безмолвный».
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 .Мне неясно, что я должен делать с этим, чтобы либо получить сертификат напрямую, либо использовать его для поиска в хранилище сертификатов, чтобы получить выбранный сертификат.