在没有设备的情况下查明私钥是否在硬件设备上

时间:2012-02-17 16:04:45

标签: .net smartcard

我想知道证书的私钥是否存储在硬件设备中 我们假设以下应用程序

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后提示插入设备(如果当时不存在smardcard)。
有没有办法获得相同的信息没有这个恼人的“请插入智能卡”对话框弹出?

1 个答案:

答案 0 :(得分:1)

我注意到我的所有智能卡证书都有两个其他证书没有的属性。可以通过CERT_SCARD_PIN_ID_PROP_IDCERT_SCARD_INFO_PROP_ID致电CertGetCertificateContextProperty查询他们。我不知道这是否是确定的,但它对我有用。

此示例应仅列出智能卡证书:

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