Узнайте, находится ли закрытый ключ на аппаратном устройстве без присутствия устройства

Я хочу узнать, хранится ли закрытый ключ сертификата на аппаратном устройстве или нет.
Предположим, что используется следующее приложение.

class Program
{
    static void Main(string[] args)
    {
        try
        {
            X509Store store = new X509Store("MY", StoreLocation.CurrentUser);
            store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);

            foreach (X509Certificate2 x509 in store.Certificates)
            {
                if (x509.HasPrivateKey)
                {
                    AsymmetricAlgorithm a = x509.PrivateKey;
                    RSACryptoServiceProvider r = a as RSACryptoServiceProvider;
                    if (null != r)
                    {
                        System.Console.WriteLine("hardware: " + r.CspKeyContainerInfo.HardwareDevice);
                        System.Console.WriteLine("Subject: " + x509.Subject);
                        System.Console.WriteLine("container: " + r.CspKeyContainerInfo.KeyContainerName);
                        System.Console.WriteLine("---");
                    }
                }
            }
        }
        catch (CryptographicException ex)
        {
            Console.WriteLine("Information could not be written out for this certificate.");
        }
    }
}

Информация, которую я ищу, находится в r.CspKeyContainerInfo.HardwareDevice.
Но, к сожалению, для хранилищ, предоставляемых базовой смарт-картой csp, мне предлагается вставить устройство после выполнения AsymmetricAlgorithm a = x509.PrivateKey (если в это время смарт-карта отсутствует).< br> Есть ли способ получить ту же информацию без всплывающего диалогового окна «пожалуйста, вставьте смарт-карту»?


person VolkerK    schedule 17.02.2012    source источник


Ответы (1)


Я заметил, что все мои сертификаты смарт-карт имеют два свойства, которых нет у других сертификатов. Их можно запросить, позвонив CertGetCertificateContextProperty с CERT_SCARD_PIN_ID_PROP_ID или CERT_SCARD_INFO_PROP_ID. Я не знаю, является ли это окончательным, но это работает для меня.

В этом примере должны быть указаны только сертификаты смарт-карт:

class Program
{
    [System.Runtime.InteropServices.DllImport("crypt32.dll", SetLastError = true)]
    extern public static bool CertGetCertificateContextProperty(IntPtr pCertContext, Int32 dwPropId, IntPtr pvData, ref Int32 pcbData);

    const int CERT_SCARD_PIN_ID_PROP_ID = 90;
    const int CERT_SCARD_INFO_PROP_ID = 91;

    static bool CertificateHasProperty(X509Certificate x509, int propId)
    {
        int cbData = 0;
        // If the property exists CertGetCertificateContextProperty returns true
        // and sets cbData to the size of buffer required to hold the data.
        return CertGetCertificateContextProperty(x509.Handle, propId, IntPtr.Zero, ref cbData);
    }

    static void Main(string[] args)
    {
        X509Store store = new X509Store("MY", StoreLocation.CurrentUser);
        store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);

        foreach (X509Certificate2 x509 in store.Certificates)
        {
            if (CertificateHasProperty(x509, CERT_SCARD_INFO_PROP_ID))
            {
                Console.WriteLine("Subject: " + x509.Subject);
            }
        }
    }
}                 
person IanS    schedule 17.03.2012