X509Store Certificates.Find FindByThumbprint的问题

时间:2011-12-09 15:58:42

标签: c# wcf certificate ssl-certificate x509certificate

当我使用方法X509Store.Certificates.Find

时,我遇到了问题
public static X509Certificate2 FromStore(StoreName storeName, 
          StoreLocation storeLocation, X509FindType findType, string findValue)
{
    X509Store store = new X509Store(storeName, storeLocation);
    store.Open(OpenFlags.ReadOnly);
    try
    {
        //findValue = "7a6fa503ab57b81d6318a51ca265e739a51ce660"
        var results = store.Certificates.Find(findType, findValue, true);

        return results[0];                
    }
    finally
    {
        store.Close();
    }
}

在这种情况下,Find方法返回0结果(results.Count == 0),但如果我将findValue作为常量,则该方法会找到证书。

public static X509Certificate2 FromStore(StoreName storeName, 
           StoreLocation storeLocation, X509FindType findType, string findValue)
{
    X509Store store = new X509Store(storeName, storeLocation);
    store.Open(OpenFlags.ReadOnly);
    try
    {         
        //findValue= "7a6fa503ab57b81d6318a51ca265e739a51ce660"
        var results = store.Certificates.Find(findType, 
                              "7a6fa503ab57b81d6318a51ca265e739a51ce660", true);
        return results[0];
    }
    finally
    {
        store.Close();
    }
}

14 个答案:

答案 0 :(得分:119)

我认为您已将指纹从Windows证书信息对话框复制粘贴到您的代码中(如果这是一个简化示例,则复制粘贴到配置文件中)。令人讨厌的是,指纹文本框中的第一个字符是invisible Unicode "left-to-right-mark" control character。尝试选择开始字符串引用和指纹的第一个字符,删除它们(这也将删除不可见的字符),并手动重新输入。

我今天遇到了这种奇怪的行为,我花了一个多小时来弄明白。我最终看到它的方法是使用调试器来检查findValue和证书对象的Thumbprint的长度和哈希码。

答案 1 :(得分:45)

我在这里得到了一些答案并将它们组合成一个静态方法,该方法负责删除特殊字符和大写字母。希望其他人可以使用它。

    public static X509Certificate2 GetCertificate(string thumbprint)
    {
        // strip any non-hexadecimal values and make uppercase
        thumbprint = Regex.Replace(thumbprint, @"[^\da-fA-F]", string.Empty).ToUpper();
        var store = new X509Store(StoreName.My, StoreLocation.LocalMachine);

        try
        {
            store.Open(OpenFlags.ReadOnly);

            var certCollection = store.Certificates;
            var signingCert = certCollection.Find(X509FindType.FindByThumbprint, thumbprint, false);
            if (signingCert.Count == 0)
            {
                throw new FileNotFoundException(string.Format("Cert with thumbprint: '{0}' not found in local machine cert store.", thumbprint));
            }

            return signingCert[0];
        }
        finally
        {
            store.Close();
        }
    }

答案 2 :(得分:22)

我有同样的问题并解决了它:

  1. 我将指纹从mmc直接复制到VS.我对这些字符串进行了比较,但没有发现任何差异。

  2. 使用hash.length检查长度,有一个区别,41对40。

  3. 通过将其复制出mmc,会在字符串中添加一个不可见的字符。


    求解:

    1. 将指纹从mmc复制到Notepad.exe
    2. 再次复制此字符串
    3. 粘贴到您的代码
    4. 它在工作。

答案 3 :(得分:8)

我成了这个受害者。不仅在指纹的Windows控制台管理单元中显示Unicode“从左到右”字符,而且它还具有小写十六进制字符,每两个字符之间有空格。 CertUtil的输出也有小写字符和空格。为了获得匹配,我必须将findValue指定为已转换为

的字符串
  1. 删除主要特殊字符
  2. 删除字符簇之间的空白
  3. 将所有字符更改为大写

答案 4 :(得分:8)

这也让我感到高兴,我在MMC复制和粘贴时写了这个函数来清理指纹:

public string CleanThumbprint(string mmcThumbprint)
    {
        //replace spaces, non word chars and convert to uppercase
        return Regex.Replace(mmcThumbprint, @"\s|\W", "").ToUpper();
    }

...
        var myThumbprint = CleanThumbprint("‎b3 ab 84 e5 1e e5 e4 75 e7 a5 3e 27 8c 87 9d 2f 05 02 27 56");
        var myCertificate = certificates.Find(X509FindType.FindByThumbprint, myThumbprint, true)[0];

答案 5 :(得分:2)

此代码应该有效。

我想您已从证书管理控制台复制了此指纹。 并且该复制的值包含在Visual Studio中不可见的unicode不可读符号。尝试删除第一个不可见的符号,如果这是我的想法, 这应该有效。

答案 6 :(得分:1)

替换代码以在商店中查找您的证书,如下所示:

var results = store.Certificates.Find(findType, findValue, true); 

只有证书有效时,bool的第3个参数才会返回证书。因此,请确保您的证书有效。如果您有自签名证书,那么只需将第3个参数传递给“false”

答案 7 :(得分:1)

我遇到了同样的事情。我在这里的任何地方找不到这个答案所以我会发布它。对我来说,X509Store查找功能似乎是平的不起作用。我通过一个简单的for循环验证了这一点,并手动检索了证书。

  X509Store store = new X509Store(StoreName.Root,StoreLocation.LocalMachine);
        store.Open(OpenFlags.ReadOnly);
        X509Certificate cert = new X509Certificate();
        for (int i = 0; i < store.Certificates.Count; i++)
        {
            if (store.Certificates[i].SerialNumber == "XXXX")
            {
                cert = store.Certificates[i];
            }
        }

答案 8 :(得分:0)

var results = store.Certificates.Find(findType, findType, true);

我认为你的意思是第二个参数是“findValue”。

答案 9 :(得分:0)

以下是上述建议的简单版本代码,对我来说很有用

 private X509Certificate2 GetCertificate()
    {
        var certStore = new X509Store("my");
        certStore.Open(OpenFlags.ReadOnly);
        try
        {
            const string thumbprint = "18 33 fe 3a 67 d1 9e 0d f6 1e e5 d5 58 aa 8a 97 8c c4 d8 c3";
            var certCollection = certStore.Certificates.Find(X509FindType.FindByThumbprint,
            Regex.Replace(thumbprint, @"\s+", "").ToUpper(), false);
            if (certCollection.Count > 0)
                return certCollection[0];
        }
        finally
        {
            certStore.Close();
        }
        return null;
    }

答案 10 :(得分:0)

我也遇到了这个不可见的Unicode字符。尝试使用记事本(Windows 10)也不适合我。最后,我使用PowerShell来获得干净的指纹十六进制:

PS C:\> $tp= (Get-ChildItem -Path Cert:\LocalMachine\My | Where-Object {$_.Subject -match "mycert"}).Thumbprint;
PS C:\> $tp

非常适合Unicode char。

答案 11 :(得分:0)

为了让你知道这个看不见的角色是什么,我看到mmc中的指纹是:75 3a ......

然后我将其复制并粘贴到我的vim中,我看到以下内容:

&lt; 200e&gt; 75 3a ...

所以在你摆脱了第一个字符“&lt; 200e&gt;”之后和额外的空间,你会没事的。

答案 12 :(得分:0)

+1代表Aasmund Eldhuset的答案(和其他答案)。

  

令人讨厌的是,指纹文本框中的第一个字符是   不可见的Unicode“从左至右标记”控制字符。

很难验证它是否存在。例如,将指纹从我的配置文件复制到VS二进制编辑器有时会得到不可见的字符,有时却不会。

此代码也未能显示问题。我单步执行代码,然后将鼠标悬停在x509Store上以查找所需的证书。

                X509Certificate2 cert2 = null;
                string storeName = StoreName.My.ToString();
                var x509Store = new X509Store(storeName, StoreLocation.LocalMachine);
                x509Store.Open(OpenFlags.ReadOnly);

                var cert3 = x509Store.Certificates[4];
                var thumbprint3 = cert3.Thumbprint;
                int gotIt = thumbprint3.CompareTo(clientCert);

答案 13 :(得分:0)

经过长期分析,这对我有用。

  1. 将指纹从证书复制到记事本中。
  2. 将指纹从记事本复制到Visual Studio。
  3. 以管理员身份运行Visual Studio。

这就像一种魅力。