Проблеми із сертифікатами магазину X509. Знайдіть 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();
    }
}

У цьому випадку метод пошуку повертає 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();
    }
}

Відповіді:


135

Припускаю, що ви скопіювали відбиток із діалогового вікна інформації про сертифікат Windows у свій код (або у файл конфігурації, якщо це спрощений приклад). Прикро, що першим символом у текстовому полі відбитка є невидимий елемент керування Unicode "зліва направо" . Спробуйте вибрати початкову цитату рядка та перший символ відбитка пальця, видаливши їх (що також позбавить від невидимого символу в проміжку), та переписавши вручну.


Я сам зазнав цієї дивної поведінки сьогодні, і мені потрібно було більше години, щоб це зрозуміти. Я нарешті побачив це за допомогою налагоджувача для перевірки довжин та хеш-кодів findValueта Thumbprintоб'єкта сертифіката, які виявилися різними. Це змусило мене перевірити масиви символів тих рядків у налагоджувачі, де з’явився невидимий символ.


4
Більш простий спосіб, ніж повторне введення, - скопіювати відбиток з діалогового вікна консолі управління сертифікатами та вставити його в текстовий редактор (наприклад, Notepad ++), після чого невидимий символ Unicode з’явиться як "?" або якийсь інший очевидно дивний персонаж. Потім ви можете зіставити цей символ і скопіювати "оновлений" рядок у свій код / ​​config / textbox.
nateirvin

2
@nateirvin: Правда (моя пропозиція переписати вручну трохи надмірна, і мене надихнуло те, як я був розчарований у той момент) - або вставте її в режим UTF-8 і увімкніть показ прихованих символів (що ще цікавіше тому що це точно показує, про якого персонажа йдеться).
Aasmund Eldhuset

1
@James Я вважаю, що його буде видалено, якщо ви також видалите навколишні цитати (як я вже писав), але справді, видалення всього рядка, безумовно, повинно позбутися цього.
Aasmund Eldhuset

1
Помилка, задокументована тут support.microsoft.com/en-us/kb/2023835 Урок не копіювати та вставляти з MMC
Дарріл Браатен,

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
Це слід прийняти як відповідь. Працює ідеально !!
Астер Вейгас,

6
Це Regex.Replace має бути "[^ \ da-fA-F]" - відбитки пальців є шістнадцятковими рядками.
Росс Паттерсон,

Дякую, що Regex щойно вирішив проблему, яку я мав після того, як півгодини лаявся кодом.
Франс

Хороший регулярний вираз для боротьби з тим надокучливим таємно прихованими персонажами вуду ...
granadaCoder

23

У мене була та ж проблема, і я її вирішив:

  1. Я скопіював відбиток пальця з mmc безпосередньо у VS. Я порівняв струни і не знайшов різниці.

  2. Перевіряючи довжину за допомогою хеш-довжини, була різниця, 41 проти 40.

До рядка додано невидимий символ Char, копіюючи його з mmc.


Вирішення:

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

Також 3-й параметр, який є bool, повертає сертифікати, лише якщо сертифікат дійсний. Тож переконайтесь, що ваш сертифікат дійсний. Якщо у вас є самопідписаний сертифікат або близько того, просто передайте третій параметр як "помилковий"


Сертифікат дійсний, тому що коли ставлений метод з жорстким кодом повертає 1 значення var results = store.Certificates.Find (findType, "7a6fa503ab57b81d6318a51ca265e739a51ce660", true); //result.Count = 1 :)
nunofamel

Чи можете ви перевірити, що таке ідентифікатор відбитка, який передається методу під час виконання?
Раджеш

правильно, я ставлю їх на вікна Imediate, і він має те саме значення :(
nunofamel

Чи змінили ви синтаксис на такий, як показано вище у вашому коді?
Раджеш

Тепер англійською мовою :) Оригінальний код у моїй програмі схожий на наведений вище, це була просто помилка копіювання + вставка :)
nunofamel

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 char.


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

Я думаю, ви маєте на увазі 2-й параметр, який має бути "findValue".


2-й параметр насправді є findValue,
nunofamel

Якщо це так, то проблема в іншому. Буквальний рядок порівняно із параметром рядкової змінної не буде розбиватися таким чином, якщо фактичний вміст не відрізняється (пробіли? Відставання від нового рядка?)
Джо

0

Щоб лише ви знали, що таке невидимий символ, я бачу відбиток пальця в mmc: 75 3a ...

Потім я копіюю та вставляю його у свій vim, я бачу таке:

<200e> 75 3a ...

Тож після того, як ви позбудетеся першого символу "<200e>" та зайвих пробілів, у вас все буде добре.


0

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

0

Після довгого аналізу ось що мені вдалося.

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

Це працює як шарм.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.