6

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?

BenMorel
  • 34,448
  • 50
  • 182
  • 322
Hamed Salameh
  • 223
  • 1
  • 5
  • 13
  • I'd check with the SmartCard reader producer, you're going to need to find out how the API of its driver work – Alex Aug 03 '12 at 07:25
  • Working with smart cards may seem like a simple task, but looks can be deceiving. Like Alex said, you might have to use your smartcard reader's API, but most likely the standard Windows API should do the trick. The article you found is a must-read and the approach is, sadly, not overkill. – dandan78 Aug 03 '12 at 07:29
  • Alex - Unfortunatly, there is no documentation or API at the reader's produer site (local producer). Thank you dandan78, If the article is a must-read, then I shall do so, and read it. Have a nice day. – Hamed Salameh Aug 03 '12 at 07:46
  • I agree, this is not a simple task *at all*. The Windows API is constantly changing and creating or appending to the logon process can result in *months* of fun. If you don't know how to do this you are much better off buying it from a card vendor that has already implemented it. – Maarten Bodewes Aug 05 '12 at 21:28
  • 2
    Windows 95, now you must be kdding, right? Right? Please? – Maarten Bodewes Aug 05 '12 at 21:29

1 Answers1

9

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

Germán Faller
  • 546
  • 7
  • 15
aiodintsov
  • 2,545
  • 15
  • 17
  • 3
    I had to make to adjustments to this in order to get it to work. You have to open the certificate store using `myStore.Open(OpenFlags.ReadOnly)` before you can get any certificates from it. Secondly, you can't loop through `myStore` instead you want to loop through `myStore.Certificates`. – mpursuit Jul 16 '15 at 08:58