X509Store证书存在问题。查找FindByThumbprint


84

使用该方法时出现问题 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();
    }
}

Answers:


135

我想您已将指纹从Windows证书信息对话框复制粘贴到您的代码中(如果是简化示例,则复制到配置文件中)。令人讨厌的是,指纹文本框中的第一个字符是不可见的Unicode“从左至右标记”控制字符。尝试选择开头的字符串引号和指纹的第一个字符,将其删除(这也将消除中间的不可见字符),然后手动重新键入它们。


今天我自己遭受了这种奇怪的行为,我花了一个多小时才弄明白了。我最终看到的方式是使用调试器检查证书对象的findValue和的长度和哈希码Thumbprint,事实证明这是不同的。这导致我在调试器中检查那些字符串的字符数组,其中显示了不可见的字符。


4
比重新键入更简单的方法是从证书管理控制台对话框中复制指纹并将其粘贴到文本编辑器(如Notepad ++)中,此时不可见的Unicode字符将显示为“?”。或其他明显奇怪的字符。然后,您可以修改该字符并将“更新的”字符串复制到您的代码/配置/文本框中。
nateirvin

2
@nateirvin:正确(我建议手动重新键入有点过大,并且受到当时我感到沮丧的启发)-或将其粘贴到UTF-8模式并打开隐藏字符的显示(这更有趣)因为它可以准确地显示出它是哪个字符)。
Aasmund Eldhuset

1
@James我相信,如果您也删除周围的引号(如我所写的),它将被删除,但确实,删除整行绝对应该摆脱它。
2014年

1
这里记录的错误support.microsoft.com/zh-cn/kb/2023835上的 课程是不要从MMC复制和粘贴
Darryl Braaten

3
对于记录,指纹不区分大小写。同样在VS2015和记事本中,我能够按Delete键删除不可见的字符-并首先使用光标键验证它是否存在
Simon_Weaver

49

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

    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
这应该作为答案。完美的作品!
Aster Veigas

6
Regex.Replace应该是“ [^ \ da-fA-F]”-指纹是十六进制字符串。
罗斯·帕特森

谢谢,正则表达式刚刚解决了我对代码发誓半小时后遇到的问题。
弗朗斯

好的正则表达式来处理令人讨厌的秘密隐藏字符伏都

23

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

  1. 我将指纹从mmc直接复制到了VS。我比较了琴弦,没有发现任何区别。

  2. 用hash.length检查长度,有一个41和40的差。

通过从mmc中复制字符串,将不可见的Char添加到字符串中。


解决方法:

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

工作正常


10

这也让我感到震惊,我编写了此功能来从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];

9

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

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

3

此代码应该起作用。

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


2

我遇到了同样的事情。我在这里的任何地方都找不到此答案,因此我将其发布。在我看来,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];
            }
        }

1

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

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

同样,仅当证书有效时,才是布尔返回证书的第三个参数。因此,请确保您的证书有效。如果您具有自签名证书,则只需将第三个参数传递为“ false”


证书有效,因为在对方法进行硬编码后返回1值var结果= store.Certificates.Find(findType,“ 7a6fa503ab57b81d6318a51ca265e739a51ce660”,true);//result.Count = 1 :)
nunofamel 2011年

您可以检查在运行时传递给方法的指纹ID是什么吗?
Rajesh

是正确的,我把它们放在中间窗口上,他的值是一样的:(
nunofamel 2011年

您是否将语法更改为上面代码中所示的语法?
Rajesh

现在是英文:)我的应用程序中的原始代码如上,只是一个复制+粘贴错误:)
nunofamel 2011年

1

这是上述建议的简单代码,对我有用

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

1

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

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

Unicode字符太多了。


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

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


第二个PARAM真的是findValue,
nunofamel

如果真是这样,那么问题就在其他地方。文字字符串与字符串变量参数不会像这样中断,除非实际内容不同(空格?尾随换行符?)
Joe

0

只是为了让您知道什么是不可见字符,我在mmc中看到的指纹是:75 3a ...

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

<200e> 75 3a ...

因此,当您除去第一个字符“ <200e>”和多余的空格后,您就可以了。


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

0

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

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

这就像一个魅力。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.