2009-02-19 26 views
5

¿Cómo me puedo asegurar de que estoy accediendo a los Certificados de mi SmartCard y no de mi tienda de certificados personales en C#? y ¿Cómo puedo hacer que mi RSACryptoProvider utilice la clave privada de mi certificado de tarjeta inteligente?Certificados de SmartCard en C#

gracias

Wally

Respuesta

3

En ocasiones, especialmente si no utiliza el nombre del contenedor de claves predeterminado en la tarjeta inteligente (recomendado por Microsoft), los certificados no se copian en el almacén de certificados local. La solución es usar crypto api para acceder a la clave con KP_CERTIFICATE, construir el certificado a partir de los datos recuperados y asignarle un nuevo RSACryptoServiceProvider construido utilizando su propio nombre de contenedor de claves.

El seudo código C# siguiente:

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

¿Estoy un poco confundido sobre cuándo se necesitaría ese código? Si conoce la línea de asunto de la tarjeta inteligente, almacénela para cada uno de sus usuarios al registrarse y luego almacene el certificado en la base de datos; luego, cada vez que alguien intente iniciar sesión, compare el certificado en la base de datos con el certificado que figura en Solicitud .ClientCertificate, ¿verdad? – Dexter

+0

Solo puede almacenar parte pública del certificado en alguna parte, y la comparación de partes públicas del certificado no es suficiente para probar la posesión de la clave privada. Por lo tanto, necesita acceso a una clave privada para firmar algunos datos y probarlo. El proveedor de cifrado a veces pondrá la clave privada disponible para el almacén de certificados de forma automática y, a veces, no. En caso de que no lo haga, esta es la forma de obtenerlo. –

+0

¿Hay algún artículo en el que encuentre este tipo de código? Tu código está un poco incompleto con las variables no declaradas. ¿Dónde hay un artículo de C# que describe este proceso de verificación de la validez de claves privadas? Siempre asumí una verificación simple de la certificación válida usando X509Certificate para verificar si el hash es un hash válido en el Certificado del cliente podría ser suficiente, pero sí, supongo que se puede falsificar con un certificado autofirmado. Cualquier información sería de gran ayuda. – Dexter

2

Usted tendrá que ir a través de su proveedor de servicios de cifrado (CSP) para su tarjeta inteligente. En Windows (2000, XP y Vista) cada vez que inserta su tarjeta inteligente en un lector de tarjeta inteligente, todos los certificados que contiene se propagan a su tienda de certificados personal. Tu clave privada permanece en tu tarjeta inteligente. Lo que eso significa es que si utiliza su certificado (por ejemplo, para firmar digitalmente un correo electrónico), se le pedirá que inserte su tarjeta inteligente. Si su tarjeta inteligente requiere un PIN, se le pedirá que ingrese. La razón de esto es que hay una ubicación para que las aplicaciones busquen certificados de usuario, su almacén de certificados personal, por lo que las aplicaciones no tienen que reescribirse para manejar certificados en tarjetas inteligentes.

+0

aplicaciones Java pueden utilizar la tarjeta inteligente/certificado sin instalar el certificado en el almacén personal. Si no está instalado antes, las aplicaciones .NET no pudieron encontrar el certificado necesario. –