User login with Smart Card for Windows UWP app

最后都变了- 提交于 2019-12-12 17:20:04

问题


This seems like such a simple thing but I have been trying to figure this out for over a week now and cannot seem to figure it out. We are creating a Windows UWP app using WinJS and would like the user to login to the app with a PIV (smart card)/PIN combination. Essentially, when the app starts it will verify that there is a smart card inserted into the device and then prompt the user for the PIN. If the PIN is validated against the smart card the app will log the user in.

We do have Windows 7 applications that currently do this and I attempted to convert that code however it appears the APIs we used are not valid for Windows UWP apps. I did post the question about those APIs but did not receive any responses (https://stackoverflow.com/questions/43344679/x509certificate2ui-class-equivalent-with-windows-uwp-and-winjs). With Windows 7 we used the X509Certificate2UI (https://msdn.microsoft.com/en-us/library/system.security.cryptography.x509certificates.x509certificate2ui(v=vs.110).aspx ) class to select a certificate which prompted the user for the PIN.

After a lot of research, I believe (and could be wrong) with Windows UWP I need to use the smart card APIs (https://docs.microsoft.com/en-us/uwp/api/windows.devices.smartcards ). I have been reading the past couple of days and went through several Microsoft documents on smart cards like this one: https://docs.microsoft.com/en-us/windows/uwp/security/smart-cards but have not been able to find a way to validate a user entered PIN against the PIN on the smart card.

From the SmartCardProvisioning class (https://docs.microsoft.com/en-us/uwp/api/windows.devices.smartcards.smartcardprovisioning ) we are able to call the requestPinChangeAsync() method which prompts the user for the current PIN and the new PIN. I am looking for similar functionality except that it only asks for the current PIN and then returns a value that will let the app know if the PIN was correct.

I have also read through Microsoft’s Hello (https://docs.microsoft.com/en-us/windows/uwp/security/microsoft-passport ) API but did not see a way to use it with smart cards.

Can anyone point me in the right direction on how to use two-factor authentication in my app using a smart card/PIN combination. It seems like I have been in a Google bubble for the past several days going round and round and need help to get out.

Thanks

edit to explain why it is not a duplicate: Not really a duplicate, both questions were asked by me and I mention the other post in the bod of the question. In the other post I was looking for an equivalent to the X509Certificate2UI class for Windows UWP with WinJS. With further research, I am thinking that might not be the correct way to go therefore with this post I am looking to see if anyone can point me in the right direction to doing two-factor authentication using a PIV (smart card) and the PIN associated with the card.

EDIT: Share code that works: Here is the WinJS code that seems to work. Not sure is there is a better way or not:

  if (certToUse != null) {
    Windows.Security.Cryptography.Core.PersistedKeyProvider.openKeyPairFromCertificateAsync(certToUse, Windows.Security.Cryptography.Core.HashAlgorithmNames.sha256, Windows.Security.Cryptography.Core.CryptographicPadding.rsaPkcs1V15).then(function (keyPair) {
      var buffer = 'data to sign'
      var data = Windows.Security.Cryptography.CryptographicBuffer.convertStringToBinary(buffer, Windows.Security.Cryptography.BinaryStringEncoding.utf16BE)
      Windows.Security.Cryptography.Core.CryptographicEngine.signAsync(keyPair, data).then(function (signed) {
        var results = Windows.Security.Cryptography.Core.CryptographicEngine.verifySignature(keyPair, data, signed)
          completeValidatePin = true
          successCallback(true)
      }, function (reason) {
          completeValidatePin = true
          errorCallback('User cancelled login')
      })
    }, function (reason) {
      completeValidatePin = true
      errorCallback('Error using certificate')
    })
  } else {
    errorCallback('Certificate not found')
  }

回答1:


I'm currently investigating your question and trying to determine if there is a good solution.

I did write the following code which I thought should work:

IReadOnlyList<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)
{
    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);                        

        }
        catch (Exception ex)
        {
            // Could not open Smart Card Key Pair
        }

        if (Key != null)
        {
            try
            {                           
                // Try to Sign with Cert Private key 
                IBuffer EncryptedBuffer = CryptographicEngine.Sign(Key, BufferToEncrypt);
            }
            catch (Exception ex)
            {
                // Could not sign                            
            }
        }
    }
}

Unfortunately, OpenKeyPairFromCertificateAsync creates a provider with a silent context so CryptographicEngine.Sign is unable to display a PIN dialog. I will have to look into it a bit more.



来源:https://stackoverflow.com/questions/43373052/user-login-with-smart-card-for-windows-uwp-app

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!