A volte, soprattutto se non si utilizza il nome del contenitore chiave predefinito sulla smart card (consigliato da Microsoft), i certificati non vengono copiati nell'archivio certificati locale. La soluzione è utilizzare crypto api per accedere alla chiave con KP_CERTIFICATE, costruire il certificato dai dati recuperati e assegnargli un nuovo RSACryptoServiceProvider costruito usando il proprio nome del contenitore chiave.
Lo pseudo codice C# segue:
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);
}
fonte
2009-03-04 10:59:35
Sono un po 'confuso su quando questo codice sarebbe necessario? Se dici di conoscere la riga dell'oggetto della smart card, la memorizzi per ciascuno dei tuoi utenti al momento della registrazione e quindi memorizzi il certificato nel DB, quindi ogni volta che qualcuno tenta di accedere, confronta il certificato in DB con il certificato fornito in Richiesta .ClientCertificate, giusto? – Dexter
È possibile memorizzare solo parte pubblica del certificato da qualche parte e il confronto tra le parti pubbliche del certificato non è sufficiente a dimostrare il possesso della chiave privata. Pertanto è necessario l'accesso con chiave privata per firmare alcuni dati e provarlo. Il provider di crittografia a volte rende disponibile la chiave privata all'archivio certificati e talvolta no. Nel caso in cui non è questo il modo per ottenerlo. –
C'è un articolo in cui hai trovato questo tipo di codice? Il tuo codice è un po 'incompleto con variabili non dichiarate. Dove c'è un articolo in C# che descrive questo processo di verifica della validità delle chiavi private. Ho sempre pensato che un semplice controllo della certificazione valida utilizzando X509Certificate per verificare se l'hash è un hash valido nel certificato client potrebbe essere sufficiente, ma sì, suppongo che possa essere simulato con un certificato autofirmato. Qualsiasi informazione sarebbe utile. – Dexter