views:

3329

answers:

2

Hi How can I ensure to I am accesing the Certificates from my SmartCard and not form my personal certificate store in c#? and How can I make my RSACryptoProvider to utilize my smart card certificate private key?

thanks

Wally

+1  A: 

You will need to go through your Cryptographic Service Provider (CSP) for your smartcard. On Windows (2000, XP, and Vista) any time you insert your smartcard into a smartcard reader all the certificates on it are propogated to your personal certificate store. Your private key stays on your smart card. What that means is if you use your certificate (for example to digitally sign an e-mail) then you are prompted to insert your smart card. If your smart card requires a PIN you will be asked to input it. The reason for this is that there is one location for applications to look for user certificates, your personal certificate store, so applications don't have to be rewritten just to handle certificates on smartcards.

Craig Delthony
A: 

Sometimes, especially if you are not using default key container name on the smart card (recommended by Microsoft), certificates are not copied to local certificate store. The solution is to use crypto api to access the key with KP_CERTIFICATE, construct certificate from the retrieved data, and assign it a new RSACryptoServiceProvider constructed using your own key container name. The pseudo C# code follows:

int reti = CryptoApi.CryptGetUserKey(_hprovider, keytype, ref userKey);
if (reti)
    reti =CryptoApi.CryptGetKeyParam(_userKey, KP_CERTIFICATE, ref  pbdata, ref pwddatalen, 0);
if (reti || pwddatalen>0){
                byte[] data = new byte[pwddatalen];
                ret  = CryptoApi.CryptGetKeyParam(_userKey, KP_CERTIFICATE, data, ref pwddatalen, 0);
                if (ret) {
                    X509Certificate2 c = new X509Certificate2(data);
                    X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
                    store.Open(OpenFlags.ReadOnly);
                    X509Certificate2Collection col = store.Certificates.Find(X509FindType.FindByThumbprint, c.Thumbprint, validonly);
                    store.Close();
                    if (col.Count != 1) {
                        //not found in store - CSP didn't copy it
                        c.PrivateKey = PrivateKey(keytype);
                        return c;
                    } else {
                        return col[0];
                    }
                }

}

   private RSACryptoServiceProvider PrivateKey (KeyType keytype){
        CspParameters csparms = new CspParameters();
        csparms.KeyContainerName = _containerName;
        csparms.ProviderName = _provider;
        csparms.ProviderType = 1;
        csparms.Flags = CspProviderFlags.UseMachineKeyStore | CspProviderFlags.UseExistingKey;
        csparms.KeyNumber = (int)keytype;
        return new RSACryptoServiceProvider(csparms);
    }
Željko Tanović