如何将 CSR 文本文件转换为 .NET Core/标准证书请求以进行签名?

问题描述

很多类似的问题,但我没有看到好的答案。

我有一个基于云的应用程序,在现场的客户站点上安装了一个代理。我想让代理在安装时生成 CSR 并通过 HTTPS 将请求上传到云服务,在那里我将使用云服务证书(代理将信任)对其进行签名并返回签名证书。此证书将用于代理身份验证、加密和文件签名。

我可以很容易地制作 CSR:

    public string GenerateAgentCsr(Guid customerId)
    {
        var domain = System.Net.NetworkInformation.IPGlobalProperties.GetIPGlobalProperties().DomainName;
        var domainDistinguishedName = string.Join(",DC=",domain.Split("."));
        var distinguishedName = $"DC={Environment.MachineName},DC={domainDistinguishedName},O={customerId}";
        var rsa = RSA.Create(1024);
        var request = new CertificateRequest(distinguishedName,rsa,HashAlgorithmName.SHA256,RSASignaturePadding.Pkcs1);
        request.CertificateExtensions.Add(new X509BasicConstraintsExtension(false,false,false));
        request.CertificateExtensions.Add(new X509KeyUsageExtension(
            X509KeyUsageFlags.DigitalSignature | X509KeyUsageFlags.DataEncipherment |
            X509KeyUsageFlags.NonRepudiation,false));

        var armored = request.AsCsr();
        return armored;
    }

    public static string AsCsr(this CertificateRequest request)
    {
        var encoded = request.CreateSigningRequest();
        var payload = Convert.ToBase64String(encoded);
        using var stream = new MemoryStream();
        using (var writer = new StreamWriter(stream,Encoding.UTF8,512,true))
        {
            writer.WriteLine("-----BEGIN CERTIFICATE REQUEST-----");
            writer.WriteLine(payload.Slice());
            writer.WriteLine("-----END CERTIFICATE REQUEST-----");
            writer.Flush();
        }

        stream.Position = 0;
        using (var reader = new StreamReader(stream))
        {
            return reader.ReadToEnd();
        }
    }

...所以我可以将其发送到云服务器,但随后我立即遇到了问题。我的计划是采用这样的方法:

    public X509Certificate2 SignCertificate(CertificateRequest csr)
    {
        var signedCert = csr.Create(GetCertificateAuthorityCertificate(),DateTimeOffset.Now,DateTimeOffset.Now.AddYears(10),new byte[] { 1,2,3,4 });
        return signedCert;
    }

...但我实际上无法将 CSR 转换为 CertificateRequest。没有 Parse 机制或构造函数允许这样做。

那么...一旦我有了 CSR,我该如何正确解析它并使用我的云服务证书对其进行签名,以便我可以将其发送回代理?

解决方法

类型可以帮助您填充 CertificateRequest 对象的唯一方法是使用 System.Formats.Asn1.AsnReader 读取数据。

签署证书请求是一项重大决定。请求是否仅使用它被授权使用的名称?它是否将自己提升到另一个颁发证书的机构?是否有任何扩展请求您不明白其含义?它是否声称是时间戳授权机构、代码签名证书或任何其他有限用途?

通过签署外部请求,您正在努力成为“真正的”CA。你在做撤销吗?你在记录发行吗?

.NET 有 SubjectAlternativeNameBuilder 来帮助构建 SAN 扩展,但没有一个很好的方法来读取它们......因为 SubjectAlternativeNames 比它们通常使用的要复杂得多。所以没有很好的方法来回答姓名问题。

如果您使用受控访问,则此方法的一个更有限的版本是以您自己的自定义格式仅传输公钥的 SubjectPublicKeyInfo 值(以及您想要包含的任何其他信息)(另请参阅{1}})。然后你知道你不会被要求做你不想做的事情。不幸的是,rsa.ExportSubjectPublicKeyInfo() 是 .NET 6 中的新功能。幸运的是,这很容易:

PublicKey.CreateFromSubjectPublicKeyInfo

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...