以编程方式与证书颁发机构通信

2024-03-27

我以编程方式处理证书并与证书颁发机构进行通信。我一直在 Windows 2008R2 上使用 C# 处理 CertClient 和 CertEnroll COM 对象。

我可以生成请求并从 CA 获取证书。我从这个例子开始:http://blogs.msdn.com/b/alejacma/archive/2008/09/05/how-to-create-a-certificate-request-with-certenroll-and-net-c.aspx http://blogs.msdn.com/b/alejacma/archive/2008/09/05/how-to-create-a-certificate-request-with-certenroll-and-net-c.aspx

我有两个我无法弄清楚的问题。首先,我如何才能访问用于生成证书的私钥? IX509PrivateKey 接口中的方法似乎不适用于我的测试环境。我给 CA 的请求与私钥不同,对吗?

第二个问题是我似乎无法弄清楚在请求证书时提供注册代理证书。此 API 的旧版本有一个方法,即 SetSignerCertificate,已使用。我在新 API 中找不到等效项。


使用注册代理证书的示例可在 MSDN 下找到代表另一个用户请求创建注册 https://technet.microsoft.com/en-us/library/ff182315(v=ws.10).aspx。该证书将安装到您指定的证书存储中,您可以像使用任何其他已安装的证书一样使用私钥。

完整示例:

// Add references to CERTENROLL (CertEnroll 1.0 Type Library) 
// and CERTCLILib (CertCli 1.0 Type Library)
using CERTCLILib;
using CERTENROLLLib;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
using X509KeyUsageFlags = CERTENROLLLib.X509KeyUsageFlags;

namespace TestSubmitEnrollment
{
    class Program
    {
        static void Main(string[] args)
        {
            string requesterName = @"DOMAIN\otherUser";
            string caName = @"CA1.DOMAIN.LOCAL\DOMAIN-CA1-CA";
            string template = "User";
            // signerCertificate's private key must be accessible to this process
            var signerCertificate = FindCertificateByThumbprint("3f817d138f32a9a8df2aa6e43b8aed76eb93a932");

            // create a new private key for the certificate
            CX509PrivateKey privateKey = new CX509PrivateKey();
            // http://blogs.technet.com/b/pki/archive/2009/08/05/how-to-create-a-web-server-ssl-certificate-manually.aspx
            privateKey.ProviderName = "Microsoft Enhanced Cryptographic Provider v1.0";
            privateKey.MachineContext = false;
            privateKey.Length = 2048;
            privateKey.KeySpec = X509KeySpec.XCN_AT_KEYEXCHANGE;
            privateKey.ExportPolicy = X509PrivateKeyExportFlags.XCN_NCRYPT_ALLOW_EXPORT_NONE;
            privateKey.Create();

            // PKCS 10 Request
            // we use v1 to avoid compat issues on w2k8
            IX509CertificateRequestPkcs10 req = (IX509CertificateRequestPkcs10)new CX509CertificateRequestPkcs10();
            req.InitializeFromPrivateKey(X509CertificateEnrollmentContext.ContextUser, privateKey, template);

            // PKCS 7 Wrapper
            var signer = new CSignerCertificate();
            signer.Initialize(false, X509PrivateKeyVerify.VerifyAllowUI, EncodingType.XCN_CRYPT_STRING_BASE64_ANY, 
                Convert.ToBase64String(signerCertificate.GetRawCertData()));

            var wrapper = new CX509CertificateRequestPkcs7();
            wrapper.InitializeFromInnerRequest(req);
            wrapper.RequesterName = requesterName;
            wrapper.SignerCertificate = signer;

            // get CSR
            var enroll = new CX509Enrollment();
            enroll.InitializeFromRequest(wrapper);
            var csr = enroll.CreateRequest();
            //File.WriteAllText("csr.p7b", csr);

            // submit
            const int CR_IN_BASE64 = 1, CR_OUT_BASE64 = 1;
            const int CR_IN_PKCS7 = 0x300;
            ICertRequest2 liveCsr = new CCertRequest();
            var disposition = (RequestDisposition)liveCsr.Submit(CR_IN_BASE64 | CR_IN_PKCS7, csr, null, caName);

            if (disposition == RequestDisposition.CR_DISP_ISSUED)
            {
                string resp = liveCsr.GetCertificate(CR_OUT_BASE64);
                //File.WriteAllText("resp.cer", resp);

                // install the response
                var install = new CX509Enrollment();
                install.Initialize(X509CertificateEnrollmentContext.ContextUser);

                install.InstallResponse(InstallResponseRestrictionFlags.AllowUntrustedRoot,
                    resp, EncodingType.XCN_CRYPT_STRING_BASE64_ANY, null);
            }
            else
            {
                Console.WriteLine("disp: " + disposition.ToString());
            }
            Console.WriteLine("done");
            Console.ReadLine();
        }

        private enum RequestDisposition
        {
            CR_DISP_INCOMPLETE = 0,
            CR_DISP_ERROR = 0x1,
            CR_DISP_DENIED = 0x2,
            CR_DISP_ISSUED = 0x3,
            CR_DISP_ISSUED_OUT_OF_BAND = 0x4,
            CR_DISP_UNDER_SUBMISSION = 0x5,
            CR_DISP_REVOKED = 0x6,
            CCP_DISP_INVALID_SERIALNBR = 0x7,
            CCP_DISP_CONFIG = 0x8,
            CCP_DISP_DB_FAILED = 0x9
        }

        private static X509Certificate2 FindCertificateByThumbprint(string sslCertThumbprint)
        {
            X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
            try
            {
                store.Open(OpenFlags.ReadOnly);

                var certs = store.Certificates.Find(X509FindType.FindByThumbprint, sslCertThumbprint, true);
                if (certs.Count > 0)
                {
                    return certs[0];
                }
                else
                {
                    throw new KeyNotFoundException();
                }
            }
            finally
            {
                store.Close();
            }
        }

        // we re-declare this to account for backcompat to 2k8
        [ComImport, Guid("884E2042-217D-11DA-B2A4-000E7BBB2B09")]
        class CX509CertificateRequestPkcs10
        {
        }
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

以编程方式与证书颁发机构通信 的相关文章

随机推荐

  • .net - C# 2.0 应用程序中的玻璃效果

    如何在 net 2 0 中的 Windows 窗体应用程序上提供 Vista 或 Mac OS X 风格的玻璃效果 这是通过使用 Vista DWM 桌面窗口管理器 API 的互操作来完成的 例如 导入这些函数 DllImport dwma
  • @BeanProperty 具有 PropertyChangeListener 支持吗?

    BeanProperty生成简单的get set方法 有没有办法自动生成此类方法并支持触发属性更改事件 例如 我想将其与 JFace 数据绑定一起使用 我也有同样的问题 并一直在密切关注可能的答案 我想我刚刚偶然发现了一个 尽管我还没有尝试
  • 类路径中的 Flutter 运行时 JAR 文件应具有相同的版本

    Building without sound null safety For more information see https dart dev null safety unsound null safety w Runtime JAR
  • 小阴谋家 - 从哪里开始?

    我刚刚打开 小阴谋家 我觉得我错过了一些东西 第一个问题问 这是一个原子吗 但我没有看到原子是什么的任何定义 我想我可以通过问题的答案推导出什么是原子 但随后它继续问 l 的 car 是什么 l 的 cdr 是什么 我不知道在问什么 这本书
  • AngularJS:工厂 $http 服务

    我试图理解 Angular 中工厂和服务的概念 我在控制器下有以下代码 init function init http post services type getSource ID TP001 success function data
  • Java:具有重复键的 Json 可以使用 Jackson 进行映射

    我有一个具有相同键但不同值的 json 文件 如下所示 domains A name a type a1 B name r type g1 A name b type b1 这是来自外部系统 如何转换json 到 java 映射对象并访问不
  • JQuery 如何 .find() 不区分大小写?

  • Fabric.loadSVGFromString 导致结果扭曲

    我用 inkscape 编辑了 SVG
  • 如何在xtable表格中放置颜色间距?

    如何在xtable表格中放置颜色间距 我使用以下说明生成表格 test table lt xtable summary test caption test floating FALSE align test table lt c l pri
  • DataGridView 中明显的内存泄漏

    如何强制 DataGridView 释放其对绑定 DataSet 的引用 我们有一个相当大的数据集显示在 DataGridView 中 并注意到 DataGridView 关闭后资源没有被释放 如果用户重复查看此报告 他们最终会收到内存不足
  • 我在 intellij 中的 jar 资源文件是只读的,我需要编辑它们

    我已经尝试了几个小时来编辑我用作库的 jar 中的 java 文件 但没有成功 我已将资源标记为内容根和源根 但我仍然无法编辑 jar 中的代码 该项目编译并运行正确 但我需要对资源文件进行调整 但不能 我尝试了所有我能想到的项目结构 难道
  • kotlin如何通过delegate使用this来实例化viewmodel

    我正在阅读 google android 架构示例并遇到了这个 有人可以向我解释这个代表是如何工作的吗 private val viewModel by viewModels
  • 如何在C++中“返回一个对象”?

    我知道这个标题听起来很熟悉 因为有很多类似的问题 但我要求问题的不同方面 我知道将东西放在堆栈上和将它们放在堆上之间的区别 在Java中我总是可以返回对 本地 对象的引用 public Thing calculateThing Thing
  • Mono 可以在 rdlc 中创建/运行报告吗?

    我从未使用过 mono 很好奇 mono 是否可以创建 运行 rdlc 报告 我正在寻找实现的是一个单声道 asp net mvc 应用程序 用于使用 rdlc 创建报告并导出为 pdf 单声道可以吗 有一些开源项目尝试在 NET 中实现
  • twitter 没有重定向到 android 应用程序中的回调 url

    我的目标是允许使用 twitter4j 登录 Twitter 我用这个作为参考 https github com Sheikh Aman Android Samples blob master 1 20Sign inWithTwitterT
  • Jsoup:忽略 SSL 错误

    我正在尝试下载https www deviantart com https www deviantart com使用 Jsoup v1 10 3 以及validateTLSCertificates false Java 8 已安装 Unli
  • 使用 OpenTok 暂停视频通话

    我一直在研究 webRTC 平台 发现 OpenTok 似乎提供了最可定制的功能 在深入研究之前 我想确保它可以满足一项关键要求 在两个用户 A 和 B 之间的 1 1 视频通话期间 我希望其中一个用户 让我们与用户 A 一起 能够接收来自
  • Django - 无法获取 highchart 来显示数据

    我尝试按照以下解决方案在 Highchart 的帮助下显示图表 通过 JSON 将 Django 数据库查询集传递到 Highcharts https stackoverflow com questions 27810087 passing
  • 在 Tensorflow 中训练简单模型 GPU 比 CPU 慢

    我在 Tensorflow 中设置了一个简单的线性回归问题 并在 1 13 1 中使用 Tensorflow CPU 和 GPU 创建了简单的 conda 环境 在 NVIDIA Quadro P600 的后端使用 CUDA 10 0 然而
  • 以编程方式与证书颁发机构通信

    我以编程方式处理证书并与证书颁发机构进行通信 我一直在 Windows 2008R2 上使用 C 处理 CertClient 和 CertEnroll COM 对象 我可以生成请求并从 CA 获取证书 我从这个例子开始 http blogs