Хобрук: Ваш путь к мастерству в программировании

Проблемы с X509Store Certificates.Find FindByThumbprint

У меня проблема при использовании метода 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();
    }
}

Ответы:


1

Я предполагаю, что вы скопировали и вставили отпечаток из диалогового окна информации о сертификате Windows в свой код (или в файл конфигурации, если это упрощенный пример). Досадно, что первый символ в текстовом поле отпечатка — это невидимая Unicode-метка "слева направо". " управляющий символ. Попробуйте выбрать кавычки открывающей строки и первый символ отпечатка, удалить их (что также избавит от невидимого символа между ними) и повторно ввести их вручную.


Сегодня я сам столкнулся с этим странным поведением, и мне потребовалось больше часа, чтобы понять это. В конце концов я увидел это, используя отладчик для проверки длины и хэш-кодов findValue и Thumbprint объекта сертификата, которые оказались разными. Это заставило меня проверить массивы символов этих строк в отладчике, где появился невидимый символ.

21.02.2012
  • Более простой способ, чем повторный ввод, — скопировать отпечаток из диалогового окна консоли управления сертификатами и вставить его в текстовый редактор (например, Notepad++), после чего невидимый символ Unicode появится в виде ? или какой-то другой явно странный персонаж. Затем вы можете удалить этот символ и скопировать «обновленную» строку в свой код/конфигурацию/текстовое поле. 08.01.2013
  • @nateirvin: Верно (мое предложение перепечатать вручную немного излишне и было вдохновлено тем, насколько я был разочарован в тот момент) - или вставьте его в режиме UTF-8 и включите отображение скрытых символов (что еще более интересно потому что он точно показывает, какой это персонаж). 14.01.2013
  • В случае сбоя в Visual Studio удалите строку, так как есть невидимый символ пробела, который вы не можете удалить по отдельности. 10.08.2014
  • @James Я считаю, что он будет удален, если вы также удалите окружающие кавычки (как я писал), но действительно, удаление всей строки определенно должно избавиться от него. 10.08.2014
  • Ошибка описана здесь support.microsoft.com/en-us/kb/2023835. урок не копировать и вставлять из MMC 17.12.2015
  • для записи отпечаток нечувствителен к регистру. также в VS2015 и блокноте я смог просто нажать «Удалить», чтобы удалить невидимый символ, и убедиться, что он был там в первую очередь с помощью клавиш курсора. 30.11.2016
  • В UTF-8 оскорбительный символ (U+200E) будет закодирован как эти три байта: 0xE2808E. 05.11.2019
  • @SSS Хороший вопрос; это будет полезно, если кто-то просматривает шестнадцатеричный дамп исходного файла в кодировке UTF-8 или использует язык, который внутренне представляет строки как UTF-8 (например, Go). Спасибо за щедрость! :-) 05.11.2019

  • 2

    Я взял некоторые из ответов здесь и объединил их в статический метод, который позаботится об удалении всех специальных символов и заглавных букв. Надеюсь, кто-то еще может использовать его.

    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();
        }
    }
    
    07.07.2014
  • Это следует принять как ответ. Работает отлично!! 16.06.2016
  • Это Regex.Replace должно быть [^\da-fA-F] - отпечатки пальцев представляют собой шестнадцатеричные строки. 11.11.2016
  • Спасибо, что Regex только что решил проблему, которая возникла у меня после получасовой ругани на код. 08.01.2017
  • Хорошее регулярное выражение, чтобы справиться с этим раздражающим вуду скрытых секретных символов... 13.09.2017

  • 3

    У меня была такая же проблема, и я решил ее:

    1. Я скопировал отпечаток пальца из mmc прямо в VS. Я сравнил струны и не нашел никакой разницы.

    2. Проверяя длину с помощью hash.length, была разница, 41 против 40.

    В строку добавляется невидимый символ Char, скопированный из mmc.


    Решение:

    1. скопируйте отпечаток пальца из mmc в Notepad.exe
    2. скопируйте эту строку еще раз
    3. вставьте в свой код

    Это работает.

    20.03.2014

    4

    Я стал жертвой этого. Мало того, что в оснастке консоли Windows отображался отпечаток пальца, отображался не только символ Unicode «слева направо», но также имелись шестнадцатеричные символы нижнего регистра с пробелами между каждыми двумя символами. Вывод CertUtil также содержал символы нижнего регистра и пробелы. Чтобы получить совпадение, мне пришлось указать findValue как строку, которая была преобразована в

    1. Удалите ведущий специальный символ,
    2. Удалите пробелы между кластерами символов,
    3. Измените все символы на заглавные.
    11.12.2013

    5

    Меня это тоже сбило с толку, я написал эту функцию для очистки отпечатка при копировании и вставке из 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];
    
    24.05.2016

    6

    Этот код должен работать.

    Я полагаю, вы скопировали этот отпечаток из консоли управления сертификатами. И это скопированное значение содержит нечитаемый символ Юникода, невидимый в Visual Studio. Попробуйте удалить первый невидимый символ, и если я думаю об этом, это должно сработать.

    02.11.2012

    7

    Я столкнулся с этим же. Я не мог найти этот ответ нигде здесь, поэтому я опубликую его. Мне кажется, что функция поиска 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];
                }
            }
    
    15.01.2014

    8

    Замените код, чтобы найти свой сертификат в магазине, как показано ниже:

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

    Также третий параметр, который является логическим, возвращает сертификаты, только если сертификат действителен. Поэтому убедитесь, что ваш сертификат действителен. Если у вас есть самоподписанный сертификат или около того, просто передайте 3-й параметр как «false».

    09.12.2011
  • Сертификат действителен, потому что при жестко запрограммированном методе метод возвращает 1 значение var results = store.Certificates.Find(findType, 7a6fa503ab57b81d6318a51ca265e739a51ce660, true); //результат.Количество = 1 :) 09.12.2011
  • Можете ли вы проверить, какой идентификатор отпечатка передается методу во время выполнения? 09.12.2011
  • правильно, я ставлю их на окна Immediate, и у него такое же значение :( 13.12.2011
  • Вы изменили синтаксис на тот, который показан выше в вашем коде? 13.12.2011
  • Теперь на английском:) Исходный код в моем приложении такой же, как и выше, это была просто ошибка копирования + вставки:) 13.12.2011
  • Можете ли вы обновить приведенный выше код только для того, чтобы кто-то еще не подумал, что это ошибка. Также убедитесь, что значение точно такое же. Просто попробуйте выполнить string.compare в коде с жестко закодированным значением и значением, которое передается в метод. 13.12.2011
  • +1 за проверку действительности сертификата - эта проверка включает цепное доверие! См.: social.msdn.microsoft.com/Forums/vstudio/en-US/ 24.10.2018

  • 9

    Вот простая версия кода для приведенных выше предложений, конечно, которая сработала для меня.

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

    10

    Я также сталкиваюсь с этим невидимым символом Unicode. Попытка использовать Блокнот (Windows 10) у меня тоже почему-то не сработала. Наконец, я использую PowerShell, чтобы получить чистый шестнадцатеричный отпечаток:

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

    ТАК много для Unicode char.

    19.06.2017

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

    Я думаю, вы имеете в виду, что вторым параметром является «findValue».

    09.12.2011
  • второй параметр действительно является findValue, 09.12.2011
  • Если это так, то проблема в другом. Буквальная строка по сравнению с параметром строковой переменной не будет разбиваться, как это, если фактическое содержимое не отличается (пробелы? завершающая новая строка?) 09.12.2011

  • 12

    Просто чтобы вы знали, что такое невидимый символ, я вижу отпечаток большого пальца в ммс: 75 3a ...

    Затем я копирую и вставляю его в свой vim, я вижу следующее:

    <200e>75 3a ...

    Поэтому после того, как вы избавитесь от первого символа «‹200e>» и лишних пробелов, все будет в порядке.

    13.09.2017

    13

    +1 за ответ Аасмунда Элдхусета (и другие ответы).

    Досадно, что первый символ в текстовом поле отпечатка является невидимым управляющим символом 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);
    
    10.12.2019

    14

    После долгого анализа вот что сработало для меня.

    1. Скопируйте отпечаток большого пальца из сертификата в блокнот.
    2. Скопируйте отпечаток большого пальца из блокнота в визуальную студию.
    3. Запустите визуальную студию от имени администратора.

    Это работает как шарм.

    23.03.2020
    Новые материалы

    Основы принципов S.O.L.I.D, Javascript, Git и NoSQL
    каковы принципы S.O.L.I.D? Принципы SOLID призваны помочь разработчикам создавать надежные, удобные в сопровождении приложения. мы видим пять ключевых принципов. Принципы SOLID были разработаны..

    Как настроить Selenium в проекте Angular
    Угловой | Селен Как настроить Selenium в проекте Angular Держите свое приложение Angular и тесты Selenium в одной рабочей области и запускайте их с помощью Mocha. В этой статье мы..

    Аргументы прогрессивного улучшения почти всегда упускают суть
    В наши дни в кругах веб-разработчиков много болтают о Progressive Enhancement — PE, но на самом деле почти все аргументы с обеих сторон упускают самую фундаментальную причину, по которой PE..

    Введение в Джанго Фреймворк
    Схема «работать умно, а не усердно» В этой и последующих статьях я познакомлю вас с тем, что такое фреймворк Django и как создать свое первое приложение с помощью простых и понятных шагов, а..

    Настольный ПК как «одно кольцо, чтобы править всеми» домашних компьютеров
    Вид после 9 месяцев использования С настольных компьютеров все началось, но в какой-то момент они стали «серверами», и мы все перешли на ноутбуки. В прошлом году я столкнулся с идеей настольных..

    Расширенные методы безопасности для VueJS: реализация аутентификации без пароля
    Руководство, которое поможет вам создавать безопасные приложения в долгосрочной перспективе Безопасность приложений часто упускается из виду в процессе разработки, потому что основная..

    стройный-i18следующий
    Представляем стройную оболочку для i18next. Эта библиотека, основанная на i18next, заключает экземпляр i18next в хранилище svelte и отслеживает события i18next, такие как languageChanged,..