ปัญหาเกี่ยวกับใบรับรอง 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();
    }
}

ในกรณีนี้วิธีการค้นหาจะส่งคืนผลลัพธ์ 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();
    }
}

คำตอบ:


136

ฉันคิดว่าคุณได้คัดลอกรหัสประจำตัวจากกล่องโต้ตอบข้อมูลใบรับรอง Windows ลงในรหัสของคุณ (หรือไปยังไฟล์กำหนดค่าหากเป็นตัวอย่างที่เรียบง่าย) รำคาญตัวละครครั้งแรกในช่องรอยนิ้วมือเป็นมองไม่เห็น Unicode "ซ้ายไปขวาเครื่องหมาย" ตัวอักษรควบคุม ลองเลือกเครื่องหมายคำพูดเปิดและอักขระตัวแรกของรหัสประจำตัวลบ (ซึ่งจะกำจัดอักขระที่มองไม่เห็นที่อยู่ระหว่างนั้นด้วย) และพิมพ์ใหม่ด้วยมือ


วันนี้ฉันต้องเผชิญกับพฤติกรรมแปลก ๆ นี้เองและฉันใช้เวลากว่าหนึ่งชั่วโมงในการคิดออก วิธีที่ฉันเห็นในที่สุดก็คือการใช้ดีบักเกอร์เพื่อตรวจสอบความยาวและรหัสแฮชของfindValueและของThumbprintวัตถุใบรับรองซึ่งแตกต่างกัน สิ่งนี้ทำให้ฉันตรวจสอบอาร์เรย์อักขระของสตริงเหล่านั้นในดีบักเกอร์ซึ่งอักขระที่มองไม่เห็นปรากฏขึ้น


4
วิธีที่ง่ายกว่าการพิมพ์ซ้ำคือการคัดลอกรหัสประจำตัวจากกล่องโต้ตอบคอนโซลการจัดการใบรับรองและวางลงในโปรแกรมแก้ไขข้อความ (เช่น Notepad ++) เมื่อถึงจุดใดอักขระ Unicode ที่มองไม่เห็นจะปรากฏเป็น "?" หรือตัวละครแปลก ๆ อื่น ๆ ที่เห็นได้ชัด จากนั้นคุณสามารถ nix อักขระนั้นและคัดลอกสตริง 'updated' ไปยัง code / config / textbox ของคุณ
nateirvin

2
@nateirvin: จริง (ข้อเสนอแนะของฉันในการพิมพ์ซ้ำด้วยมือเป็นเรื่องที่มากเกินไปและได้รับแรงบันดาลใจจากความผิดหวังในตอนนั้น) - หรือวางในโหมด UTF-8 และเปิดการแสดงอักขระที่ซ่อนอยู่ (ซึ่งน่าสนใจยิ่งกว่า เพราะมันแสดงให้คุณเห็นว่ามันคือตัวละครใด)
Aasmund Eldhuset

1
@ เจมส์ฉันเชื่อว่ามันจะถูกลบหากคุณลบเครื่องหมายคำพูดรอบข้างด้วย (ตามที่ฉันเขียน) แต่จริงๆแล้วการลบทั้งบรรทัดควรกำจัดมันออกไปอย่างแน่นอน
Aasmund Eldhuset

1
บันทึกข้อบกพร่องไว้ที่นี่support.microsoft.com/en-us/kb/2023835 บทเรียนไม่ได้คัดลอกและวางจาก MMC
Darryl Braaten

3
สำหรับบันทึกรหัสประจำตัวจะไม่คำนึงถึงตัวพิมพ์เล็กและใหญ่ นอกจากนี้ใน VS2015 และ notepad ฉันสามารถเพียงแค่กด Delete เพื่อลบอักขระที่มองไม่เห็น - และตรวจสอบว่ามีอยู่ตั้งแต่แรกด้วยปุ่มเคอร์เซอร์
Simon_Weaver

50

ฉันได้รับคำตอบบางส่วนที่นี่และรวมเข้ากับวิธีการคงที่ซึ่งดูแลการลบอักขระพิเศษและตัวพิมพ์ใหญ่ทุกอย่าง หวังว่าจะมีคนอื่นใช้บ้าง

    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]" - รหัสประจำตัวเป็นสตริงเลขฐานสิบหก
Ross Patterson

ขอบคุณที่ Regex เพิ่งแก้ไขปัญหาที่ฉันพบหลังจากสาบานรหัสเป็นเวลาครึ่งชั่วโมง
Frans

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

ฉันตกเป็นเหยื่อของสิ่งนี้ ไม่เพียง แต่จะมีอักขระ Unicode "ซ้ายไปขวา" ในการแสดงรหัสประจำตัวของคอนโซล Windows เท่านั้น แต่ยังมีอักขระเลขฐานสิบหกตัวพิมพ์เล็กโดยมีช่องว่างระหว่างทุกสองอักขระ เอาต์พุตของ CertUtil ยังมีอักขระตัวพิมพ์เล็กและช่องว่าง เพื่อให้ได้การจับคู่ฉันต้องระบุ findValue เป็นสตริงที่ถูกเปลี่ยนเป็น

  1. ลบอักขระพิเศษนำหน้า
  2. ลบช่องว่างระหว่างกลุ่มอักขระ
  3. เปลี่ยนทุกตัวอักษรที่จะเป็นตัวพิมพ์ใหญ่

3

รหัสนี้ควรใช้งานได้

ฉันคิดว่าคุณได้คัดลอกรหัสประจำตัวนี้จากคอนโซลการจัดการใบรับรอง และค่าที่คัดลอกนั้นมีสัญลักษณ์ Unicode ที่ไม่สามารถอ่านได้ซึ่งมองไม่เห็นใน Visual Studio ลองลบสัญลักษณ์แรกที่มองไม่เห็นและถ้าเป็นสิ่งที่ฉันคิดก็น่าจะใช้ได้


2

ฉันเจอสิ่งเดียวกันนี้ ฉันไม่พบคำตอบนี้ที่ไหนเลยฉันจะโพสต์ สำหรับฉันดูเหมือนว่าฟังก์ชันค้นหา X509Store จะแบนไม่ทำงาน ฉันตรวจสอบสิ่งนี้โดยง่ายสำหรับการวนซ้ำและดึงใบรับรองด้วยตนเอง

  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 ซึ่งเป็นใบรับรองการส่งคืนบูลก็ต่อเมื่อใบรับรองนั้นถูกต้อง ดังนั้นตรวจสอบให้แน่ใจว่าใบรับรองของคุณถูกต้อง หากคุณมีใบรับรองที่ลงนามด้วยตนเองหรือมากกว่านั้นให้ส่งพารามิเตอร์ตัวที่ 3 ให้เป็น "เท็จ"


ใบรับรองถูกต้องเพราะเมื่อใส่ฮาร์ดโค้ดวิธีการคืนค่า 1 ค่า var ผลลัพธ์ = store.Certificates.Find (findType, "7a6fa503ab57b81d6318a51ca265e739a51ce660" จริง); //result.Count = 1 :)
nunofamel

คุณสามารถตรวจสอบรหัสประจำตัวที่ถูกส่งผ่านขณะรันไทม์ไปยังเมธอดได้หรือไม่?
Rajesh

ถูกต้องฉันวางไว้บนหน้าต่าง Imediate และเขามีค่าเท่ากัน :(
nunofamel

คุณเปลี่ยนไวยากรณ์เป็นแบบที่แสดงไว้ด้านบนในโค้ดของคุณหรือไม่?
Rajesh

ตอนนี้เป็นภาษาอังกฤษ :) รหัสเดิมในแอปพลิเคชันของฉันเป็นเหมือนข้างต้นมันเป็นเพียงข้อผิดพลาดในการคัดลอกและวาง :)
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 ที่มองไม่เห็นนี้เช่นกัน การลองใช้ Notepad (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);

ฉันคิดว่าคุณหมายถึงพารามิเตอร์ตัวที่ 2 เป็น "findValue"


พารามิเตอร์ตัวที่ 2 คือ findValue
nunofamel

หากเป็นเช่นนั้นแสดงว่าปัญหาอยู่ที่อื่น สตริงลิเทอรัลเทียบกับพารามิเตอร์ตัวแปรสตริงจะไม่แตกเช่นนี้เว้นแต่เนื้อหาจริงจะแตกต่างกัน (เว้นวรรค? ต่อท้ายบรรทัดใหม่?)
โจ

0

เพื่อให้คุณรู้ว่าอักขระล่องหนคืออะไรฉันเห็นรหัสประจำตัวใน mmc คือ: 75 3a ...

จากนั้นฉันคัดลอกและวางในกลุ่มของฉันฉันเห็นสิ่งต่อไปนี้:

<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. คัดลอกการพิมพ์นิ้วหัวแม่มือจากแผ่นจดบันทึกไปยังสตูดิโอภาพ
  3. เรียกใช้ Visual Studio ในฐานะผู้ดูแลระบบ

การทำงานนี้เหมือนมีเสน่ห์

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.