2009-02-19 7 views
5

Как я могу обеспечить получение сертификатов с моей смарт-карты, а не создание своего личного хранилища сертификатов в C#? и как я могу заставить свой RSACryptoProvider использовать секретный ключ сертификата смарт-карты?Сертификаты от SmartCard в C#

благодаря

Уолли

ответ

3

Иногда, особенно если вы не используете имя контейнера по умолчанию на смарт-карте (рекомендуется Microsoft), сертификаты не копируются в локальное хранилище сертификатов. Решением является использование криптоапи для доступа к ключу с помощью KP_CERTIFICATE, создание сертификата из извлеченных данных и назначение ему нового RSACryptoServiceProvider, построенного с использованием вашего собственного имени контейнера ключа.

Псевдо C# код следующим образом:

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); 
} 
+0

Я немного смущен, когда такой код понадобится? Если вы знаете строку темы смарт-карты, то вы храните ее для каждого из своих пользователей при регистрации, а затем храните сертификат в БД, а затем каждый раз, когда кто-то пытается войти в систему, сравните сертификат в БД с сертификатом, указанным в запросе .ClientCertificate, правильно? – Dexter

+0

Вы можете хранить публичную часть сертификата где-то - и сравнивать открытые части сертификата недостаточно, чтобы доказать наличие закрытого ключа. Поэтому вам нужен доступ к секретному ключу, чтобы подписать некоторые данные и доказать это. Crypto-провайдер иногда будет автоматически предоставлять доступный закрытый ключ к хранилищу сертификатов, а иногда и нет. Если это не так, то это способ получить это. –

+0

Есть статья, в которой вы нашли этот тип кода? Ваш код немного неполный с необъявленными переменными. Где есть статья C#, которая описывает этот процесс проверки правильности секретных ключей. Я всегда считал, что простая проверка действительной сертификации с использованием X509Certificate для проверки того, является ли хеш допустимым хэшем в сертификате клиента, может быть достаточно, но, я полагаю, его можно подделать с помощью самозаверяющего сертификата. Любая информация будет полезна. – Dexter

2

Вам нужно будет пройти через Cryptographic Service Provider (CSP) для смарт-карт. В Windows (2000, XP и Vista) каждый раз, когда вы вставляете свою смарт-карту в считыватель смарт-карт, все сертификаты на ней распространяются на ваше личное хранилище сертификатов. Ваш закрытый ключ остается на вашей смарт-карте. Это означает, что если вы используете свой сертификат (например, для цифровой подписи по электронной почте), вам будет предложено вставить смарт-карту. Если вашей смарт-карте требуется PIN-код, вам будет предложено ввести его. Причина этого заключается в том, что для приложений требуется одно место для поиска сертификатов пользователей, вашего личного хранилища сертификатов, поэтому приложения не должны переписываться только для обработки сертификатов на смарт-картах.

+0

Java приложения могут использовать смарт-карты/сертификата без установки сертификата на персональном хранилище. Если он еще не установлен, .NET-приложениям не удалось найти необходимый сертификат. –