【问题标题】:Is there a C# wrapper for cryptuiapi.h and wincrypt.h?cryptuiapi.h 和 wincrypt.h 是否有 C# 包装器?
【发布时间】:2021-03-20 20:29:03
【问题描述】:

我有一个 C++ 实现

  1. 根据颁发者搜索证书

  2. 验证这些证书

  3. 如果有多个证书

    一个。在自己的商店中设置证书

    b.使用 CryptUIDlgSelectCertificateFromStore 显示“选择证书”窗口

  4. 从证书中返回一个特定的值

这是在 Windows MFC 程序中完成的。现在我必须在命令行程序中执行此操作。我希望为此使用 C#,因为它更容易开发并且您可以使用 NUGET 包。

cryptuiapi.hwincrypt.h 是否有一个好的“官方”C# 包装器?我找到了这些:

https://referencesource.microsoft.com/#system/security/system/security/cryptography/cryptoapi.cs https://referencesource.microsoft.com/#WsatUI/MMCUI/MMCSafeNativeMethods.cs,95a3d8346740ba05

...但是如果某处有更好的实现 (=NUGET),我不喜欢复制代码。

我使用的功能是:

CertOpenStore
CertCloseStore
CertEnumCertificatesInStore
CryptUIDlgSelectCertificateFromStore
CertVerifyRevocation
CertVerifyTimeValidity
CryptAcquireCertificatePrivateKey
CryptSignCertificate
CertFindCertificateInStore
CertGetIntendedKeyUsage
CertNameToStr
CertDuplicateCertificateContext
CertAddCertificateContextToStore

据我所知,我有 4 个选择:

  1. 使用 c# X509Store 实现整个事情,但我还没有找到 c# 的 CryptUIDlgSelectCertificateFromStore。我可以使用 pinvoke,但我认为我应该将 pinvoke 用于所有功能。
  2. 在非托管 C++ 中实现整个过程并使用现有代码。我的主要项目是 BIG 和 OLD,因此仅提取有用的功能很复杂。
  3. 在 C# 中实现控制台应用程序,引用 C++ CLR 包装器,该包装器又引用带有非托管代码的 C++ dll。
  4. 在 C# 中实现并使用上述 pinvoke 函数,这些函数可能是 PIA,因为 UNICODE/ASCII 问题。

【问题讨论】:

  • "我可以使用 pinvoke,但我认为我应该对所有功能使用 pinvoke。" -- 我不同意。我的首选方法是在可能的情况下使用 X509Store,但如果有一个您无法通过这种方式访问​​的功能,请直接对其进行 pinvoke。 X509Store.StoreHandle 已公开,因此您可以这样做。
  • 哦,谢谢!这就是我要做的。
  • (并且X509Certificate2 有一个构造函数,它采用PCCERT_CONTEXT,用于另一种方式)
  • 不错:我发现了这个docs.microsoft.com/en-us/dotnet/api/…

标签: c# c++ certificate


【解决方案1】:

为了不让别人浪费时间,这是我发现的:

你可以使用

using System.Security.Cryptography.X509Certificates;

...

public X509Certificate2 Authenticate()
    {

        X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
        store.Open(OpenFlags.OpenExistingOnly);
        X509Store storeToShow = new X509Store("teststore", StoreLocation.CurrentUser);
        storeToShow.Open(OpenFlags.ReadWrite);
        foreach (var certificate in store.Certificates)
        {
            VerboseLevel_2($"Examining {certificate.ToUsefulName()}");
            if(!certificate.CanKeyDoKeyExchange())
            {
                VerboseLevel_2($"No digintal key usage: {certificate.ToUsefulName()}");
                continue;
            }
            if (!AcceptedIssuerNames.Any(a => certificate.IssuerName.Name.Contains(a)))
            {
                VerboseLevel_2($"Not present in accepted issuers: {certificate.ToUsefulName()}");
                continue;
            }
            VerboseLevel_1($"Found {certificate.ToUsefulName()}");
            storeToShow.Add(certificate);
        }
        X509Certificate2 choosenCert = null;
        if (storeToShow.Certificates.Count > 2)
        {
            X509Certificate2Collection scollection = X509Certificate2UI.SelectFromCollection(storeToShow.Certificates, 
                "Test Certificate Select", "Select a certificate from the following list to get information on that certificate", X509SelectionFlag.SingleSelection);
            choosenCert = scollection[0];
        }

        //https://stackoverflow.com/questions/53369841/c-sharp-x509certificate2-verify-without-revocation-test
        if (choosenCert != null && choosenCert.Verify())
        {
            return choosenCert;
        }
        return null;
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-09-10
    • 1970-01-01
    • 2013-08-26
    • 1970-01-01
    • 1970-01-01
    • 2021-04-03
    • 2015-11-04
    • 2011-06-29
    相关资源
    最近更新 更多