I'm using a Gemalto IDPrime .NET smart card for my application. The following method encrypts some bytes and displays the signature:
private static void SimpleDataEncryption()
{
var csp = new CspParameters(1, "Microsoft Base Smart Card Crypto Provider")
{
Flags = CspProviderFlags.UseDefaultKeyContainer
};
var rsa = new RSACryptoServiceProvider(csp);
var data = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7 };
Console.WriteLine("Data : " + BitConverter.ToString(data));
var sig = rsa.SignData(data, "SHA1");
Console.WriteLine("Signature : " + BitConverter.ToString(sig));
var verified = rsa.VerifyData(data, "SHA1", sig);
Console.WriteLine("Verified : " + verified);
}
So far, this methods works flawlessly.
My problem is that each time the application is started, Windows prompts the user to reenter the PIN. The documentation on Smart Card Architecture states the following:
The Base CSP internally maintains a per-process cache of the PIN. The PIN is encrypted and stored in memory.
I found a way to set the PIN of a smartcard programmatically using the advapi32.dll
, but this approach seems very hackish to me since the PIN has to be passed as clear text.
So my question is:
Is there a way supported by .NET to cache the PIN for the smart card the first time the user enters it correctly and use it each time until the PIN is changed by the user?
As mentioned above, .Net crypto API manages to work with smart card, and it caches password per process for performance.
So if you still use .Net crypto API and want the password to be cached between app restarts, you have to cache password yourself. Of course, you face security risks. The user password can be changed out side .Net, so you can not receive a change event. You can prompt the user to update the password when password error raises during authenticating with smartcard.