Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to read credentials from a SmartCard in c#

In my organization, users must use SmartCard for interactive login to a Windows stations (95,Vista and 7). almost daily, we need to read the credentials stored in the SmartCard and compaire them with the ActiveDirectory, without implementing a custom credentials manager. The fields we compare are: userPrincialName and sAMAccountName.

Can you please show me a code that demonstrates how to read the credentials from the SmartCard or guide me to an article / code on the internet?

A search over internet suggeted implementing credentials manager or using other languages (like C, C++). Also, I came across this article : http://www.codeproject.com/Articles/17013/Smart-Card-Framework-for-NET written by orouit, which is a framework for working with SmartCards - but I think this too much for my simple task. What do you think?

like image 540
Hamed Salameh Avatar asked Feb 20 '23 15:02

Hamed Salameh


1 Answers

Well if developing under windows, once you insert smart card windows will fetch all certificates from the smart card place them to the My certificate store.

var smartCardCerts = new List<X509Certificate2>();
var myStore = new X509Store(StoreName.My, StoreLocation.CurrentUser);
myStore.Open(OpenFlags.ReadOnly);
foreach(X509Certificate2 cert in myStore.Certificates)
{
  if( !cert.HasPrivateKey ) continue; // not smartcard for sure
  var rsa = cert.PrivateKey as RSACryptoServiceProvider;
  if( rsa==null ) continue; // not smart card cert again
  if( rsa.CspKeyContainerInfo.HardwareDevice ) // sure - smartcard
  {
     // inspect rsa.CspKeyContainerInfo.KeyContainerName Property
     // or rsa.CspKeyContainerInfo.ProviderName (your smartcard provider, such as 
     // "Schlumberger Cryptographic Service Provider" for Schlumberger Cryptoflex 4K
     // card, etc
     var name = cert.Name;
     rsa.SignData(); // to confirm presence of private key - to finally authenticate
  }
}

basically a lot of crypto API is available via .NET nowdays. But you could also use API directly Crypto API

for example you could access smart card directly via

CryptAcquireContext(&hProv,"\\.\<Reader Name>\<Container Name>",...)

where reader name is card reader name and container name is whatever rsa.KeyContainerName in code snippet above. There are multiple ways to access information like that and Crypto API is not very consistent or straightforward. as a hint .NET version of CryptAcquireContext is RSACryptoServiceProvider with CspParameters where you can specify container name if needed.

Well finding user in ActiveDirectory may be done via System.DirectoryServices.DirectoyEntry and System.DirectoryServices.DirectorySearcher, but do not forget System.DirectoryServices.ActiveDirectory.Forest and related API which makes some things a lot easier to figure out.

You would be able to get

like image 60
aiodintsov Avatar answered Feb 27 '23 23:02

aiodintsov