在UWP应用中读取系统证书信息

在Windows里,我们可以通过certmgr.msc查看和管理系统证书,这个工具是Windows自带的。

然而,如果我们希望在UWP应用中查看这些证书,该怎么做呢?

首先,我所介绍的方法其实不仅仅适用于UWP,事实上这是来自于我的一个WPF应用里的。正因为微软发布了.NET Standard 2.0标准,允许我们跨WPF以及UWP应用使用同一套代码,这就是我为何能够最终完成一个UWP版本的demo。

样例工程可以在我的GitHub找到 https://github.com/EdiWang/Cert-Scanner

解下来看看代码,核心代码如下:

需要引用的命名空间是System.Security.Cryptography.X509Certificates,如果你希望亲自实验这段代码,请记得引用这个命名空间。

public class SystemStorageCertificationScanner : CertificationScanner
{
    public override IEnumerable<CertInfo> ScanCertificates()
    {
        foreach (StoreLocation loc in Enum.GetValues(typeof(StoreLocation)))
        {
            foreach (StoreName n in Enum.GetValues(typeof(StoreName)))
            {
                X509Store store = new X509Store(n, loc);
                store.Open(OpenFlags.ReadOnly);
                foreach (var storeCertificate in store.Certificates)
                {
                    var certInfo = new CertInfo()
                    {
                        Subject = storeCertificate.Subject,
                        FriendlyName = storeCertificate.FriendlyName,
                        Issuer = storeCertificate.Issuer,
                        Version = storeCertificate.Version,
                        Thumbprint = storeCertificate.Thumbprint,
                        StoreLocation = loc.ToString(),
                        ExpDate = DateTime.Parse(storeCertificate.GetExpirationDateString()),
                        Abstract = storeCertificate.ToString()
                    };
                    yield return certInfo;
                }
                store.Close();
            }
        }
    }
}

这个例子里,StoreLocation 是一个枚举类型,只包含2个成员: CurrentUser, LocalMachine

StoreName 是另一个枚举,表示不同种类的证书的类别名称,成员如下:

public enum StoreName
{
  AddressBook = 1,
  AuthRoot = 2,
  CertificateAuthority = 3,
  Disallowed = 4,
  My = 5,
  Root = 6,
  TrustedPeople = 7,
  TrustedPublisher = 8,
}

解下来,我们就可以通过遍历每一个X509Store对象来获取它存储的证书。但请注意,每次操作我们都必须打开(open)和关闭(close)X509Store对象。

CertInfo 是我写的一个自定义类型,目的是为了让更加易于使用和显示证书信息。

public class CertInfo
{
    public string Subject { get; set; }
    public string FriendlyName { get; set; }
    public string Issuer { get; set; }
    public string Thumbprint { get; set; }
    public int Version { get; set; }
    public string StoreLocation { get; set; }
    public DateTime ExpDate { get; set; }
    public bool IsExpired => ExpDate < DateTime.Now;
    public string Abstract { get; set; }
}

为了让代码设计更加装逼,我添加了接口和抽象类。这些仅供代码设计参考,实际上如果你想直接了当写一个读取证书的逻辑,这些是没必要的。

public interface ICertificationScanner
{
    IEnumerable<CertInfo> ScanCertificates();
}
public abstract class CertificationScanner : ICertificationScanner
{
    public abstract IEnumerable<CertInfo> ScanCertificates();
}

我建立的UWP引用使用了 Windows Template Studio, 它提供了Telerik Data Grid控件,可以方便我们显示证书信息。并且我也使用了MvvM模式,在这里我就不讲解具体步骤了,因为和本文话题无关。

假设我们已经在应用里引用了Telerik Data Grid,解下来最直观的做法就是加一行XAML代码:

<tg:RadDataGrid ColumnDataOperationsMode="Flyout" x:Name="grid" ItemsSource="{x:Bind ViewModel.Source}" />

然后在ViewModel里获取数据

public class SystemCertsViewModel : ViewModelBase
{
    public SystemStorageCertificationScanner SysCertificationScanner { get; set; }


    public SystemCertsViewModel()
    {
        SysCertificationScanner = new SystemStorageCertificationScanner();
    }


    public ObservableCollection<CertInfo> Source => SysCertificationScanner.ScanCertificates().ToObservableCollection();
}

在这个例子里,ToObservableCollection是我的一个UWP助手库提供的方法,可以通过NuGet安装:

PM> Install-Package Edi.Uwp.Helpers

现在,运行结果就是

最后,需要完整样例代码,可以在我的GitHub找到:https://github.com/EdiWang/Cert-Scanner

原文发布于微信公众号 - 汪宇杰博客(ediwangblog)

原文发表时间:2018-07-19

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

扫码关注云+社区

领取腾讯云代金券