代码之家  ›  专栏  ›  技术社区  ›  NineBerry

使用pure生成并签署证书请求。net框架

  •  42
  • NineBerry  · 技术社区  · 7 年前

    我试着用纯的。net代码创建证书请求,并根据现有CA证书(在Windows证书存储中或作为单独文件)从证书请求创建证书。

    我知道我有课程 X509Certificate X509Certificate2 可以加载证书并访问其信息,但在 System.Security.Cryptography 命名空间,可用于创建证书请求或对此类证书请求进行签名以创建新的签名证书。

    尽管 documentation on the System.Security.Cryptography.Pkcs namespace 说:

    系统。安全密码学。Pkcs命名空间提供编程 公钥加密标准(PKCS)的要素,包括 签名数据、交换密钥、, 正在请求证书 , 公钥加密和解密等安全功能。

    那么,我如何创建一个证书请求并满足该请求以仅使用pure创建一个新的X509证书呢。来自的净类别 System.Security.Cryptography ?


    注:

    • 我不想使用像openssl或MakeCert这样的外部可执行文件
    • 我不想使用BouncyCastle
    • 我不想使用Windows Certificate Enrollment API
    • 我不想使用本机Win32 API函数
    2 回复  |  直到 3 年前
        1
  •  75
  •   Community Mike Causer    3 年前

    简单回答:你可以从开始。NET Framework 4.7.2。

    此功能最初添加到。NET Core 2.0的形式 CertificateRequest 类,它可以生成PKCS#10证书签名请求或X.509(自签名或链接)公钥证书。

    该功能的类在中提供。NET Framework 4.7.2。

    using (RSA parent = RSA.Create(4096))
    using (RSA rsa = RSA.Create(2048))
    {
        CertificateRequest parentReq = new CertificateRequest(
            "CN=Experimental Issuing Authority",
            parent,
            HashAlgorithmName.SHA256,
            RSASignaturePadding.Pkcs1);
    
        parentReq.CertificateExtensions.Add(
            new X509BasicConstraintsExtension(true, false, 0, true));
    
        parentReq.CertificateExtensions.Add(
            new X509SubjectKeyIdentifierExtension(parentReq.PublicKey, false));
    
        using (X509Certificate2 parentCert = parentReq.CreateSelfSigned(
            DateTimeOffset.UtcNow.AddDays(-45),
            DateTimeOffset.UtcNow.AddDays(365)))
        {
            CertificateRequest req = new CertificateRequest(
                "CN=Valid-Looking Timestamp Authority",
                rsa,
                HashAlgorithmName.SHA256,
                RSASignaturePadding.Pkcs1);
    
            req.CertificateExtensions.Add(
                new X509BasicConstraintsExtension(false, false, 0, false));
    
            req.CertificateExtensions.Add(
                new X509KeyUsageExtension(
                    X509KeyUsageFlags.DigitalSignature | X509KeyUsageFlags.NonRepudiation,
                    false));
    
            req.CertificateExtensions.Add(
                new X509EnhancedKeyUsageExtension(
                    new OidCollection
                    {
                        new Oid("1.3.6.1.5.5.7.3.8")
                    },
                    true));
    
            req.CertificateExtensions.Add(
                new X509SubjectKeyIdentifierExtension(req.PublicKey, false));
    
            using (X509Certificate2 cert = req.Create(
                parentCert,
                DateTimeOffset.UtcNow.AddDays(-1),
                DateTimeOffset.UtcNow.AddDays(90),
                new byte[] { 1, 2, 3, 4 }))
            {
                // Do something with these certs, like export them to PFX,
                // or add them to an X509Store, or whatever.
            }
        }
    }
    

    如果您仍停留在旧版本上,请给出更长的回答:要在不添加任何新的P/Invokes的情况下实现您的目标,您需要阅读并理解以下文档:

    • ITU-T X.680 -201508,ASN。1语言
    • IETF RFC 5280 或ITU-T X.509 ,解释X.509证书中字段的文档。
    • IETF RFC 2986 ,解释PKCS#10证书签名请求
    • ITU-T X.690 ,解释了ASN的BER编码系列。1(包括DER),它告诉您如何读写字节以获得X.509/PKCS#10中的语义。

    然后您可以编写一个DER写入/读取程序,只需发出所需的字节。

        2
  •  2
  •   Dharman chazomaticus    3 年前

    我不能对上述答案发表评论,所以这只是一个评论。 @基思

    如果问题是用于服务器证书的私钥丢失了私钥,我希望这可以解释发生的情况。

    要在上述答案中组合公钥和私钥,

    cert = RSACertificateExtensions.CopyWithPrivateKey(cert, rsa);

    这将把私钥与证书捆绑在一起,以便导出到PFX File.WriteAllBytes("filename", cert.Export(X509ContentType.Pfx, "passphrase for export"));

    对于上面提供的示例。 方法 CreateSelfSigned 返回a X509Certificate2 附加了公钥和私钥的对象。 其中,与对根或下级签名时一样 这个 Create 方法将仅在 X509证书2 对象

    我认为这是因为通常的证书方法将使用CSR进行签名,并返回公钥供客户端接受,而客户端永远不会向签名服务器公开私钥。