Home View all certificates in User store
Post
Cancel

View all certificates in User store

This short post shows how to list certificates from the Current User (Personal) certificate store using C#. The code below prints a table with certificate thumbprints and the certificate common name (CN). It uses Spectre.Console to render a friendly table but the certificate logic itself does not depend on that library.

Usage notes:

  • The snippet reads from the Current User personal store (StoreName.My, StoreLocation.CurrentUser).
  • Thumbprints are printed in-dim to make them easy to copy; CN is truncated to 40 characters for readability.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
#: package Spectre.Console@0.49.1

using System;
using System.Security.Cryptography.X509Certificates;
using Spectre.Console;
using System.Text.RegularExpressions;
using System.Linq;

// Query the Current User - Personal certificate store
var store = new X509Store(StoreName.My, StoreLocation.CurrentUser);

try
{
    // Open the certificate store in read-only mode
    store.Open(OpenFlags.ReadOnly);
    
    // Get all certificates from the store
    var certificates = store.Certificates;
    
    if (certificates.Count == 0)
    {
        AnsiConsole.MarkupLine("[yellow]No certificates found in the Current User - Personal store.[/]");
        return;
    }
    
    // Create a table to display the certificates
    var table = new Table();
    table.AddColumn("[bold]Thumbprint[/]");
    table.AddColumn("[bold]Common Name (CN)[/]");
    
    // Sort certificates alphabetically by thumbprint and add to table
    foreach (X509Certificate2 cert in certificates.Cast<X509Certificate2>().OrderBy(c => c.Thumbprint))
    {
        // Extract CN from subject using regex
        var subject = cert.Subject ?? "";
        var cnMatch = Regex.Match(subject, @"CN=([^,]+)");
        var commonName = cnMatch.Success ? cnMatch.Groups[1].Value.Trim() : "N/A";
        
        // Trim CN to 40 characters
        if (commonName.Length > 40)
        {
            commonName = commonName.Substring(0, 40) + "...";
        }
        
        var thumbprint = cert.Thumbprint ?? "N/A";
        
        table.AddRow(
            $"[dim]{thumbprint}[/]",
            commonName.EscapeMarkup()
        );
    }
    
    // Display header
    AnsiConsole.MarkupLine($"[green]Found {certificates.Count} certificate(s) in Current User - Personal store:[/]");
    AnsiConsole.WriteLine();
    
    // Render the table
    AnsiConsole.Write(table);
}
catch (Exception ex)
{
    AnsiConsole.MarkupLine($"[red]Error accessing certificate store: {ex.Message}[/]");
}
finally
{
    // Always close the store
    store.Close();
}

Run with the new single-file dotnet run feature (example assumes the file is named list-certs.cs):

dotnet run .\list-certs.cs
This post is licensed under CC BY 4.0 by the author.

How to generate prompts for Copilot by Copilot

-