【问题标题】:How to create a self signed certificate with a CA certificate containing the basic constraint extension with subject type as CA如何使用包含主题类型为 CA 的基本约束扩展的 CA 证书创建自签名证书
【发布时间】:2022-01-08 23:59:42
【问题描述】:

我正在尝试使用 azure rest api 创建应用程序网关。我正在使用我使用以下文档生成的自签名证书:

https://docs.microsoft.com/en-us/azure/application-gateway/self-signed-certificates

当我发送创建应用程序网关的请求时,我收到以下错误:

不包含任何 CA 证书。 CA 证书包含主题类型为 CA 的基本约束扩展。

我尝试将根证书与客户端证书结合起来,但这似乎没有帮助。

该解决方案需要自动化,并且将在 Windows 机器上运行,这里是与文档匹配的相关源代码(C#):

        Process process = null;
        var processInfo = new ProcessStartInfo();
        processInfo.FileName = AzureNames.OpenSSLBinaryLocation;
        processInfo.CreateNoWindow = true;
        processInfo.UseShellExecute = false;
        processInfo.RedirectStandardError = true;
        processInfo.RedirectStandardOutput = true;
        processInfo.WorkingDirectory = workingDirectory;
        
        processInfo.Arguments = string.Format("ecparam -out {0}.key -name prime256v1 -genkey", AzureNames.CertificateRoot);
        process = Process.Start(processInfo);
        process.WaitForExit();

        processInfo.Arguments = string.Format("req -new -sha256 -key {0}.key -out {0}.csr -subj \"/C=US/ST=Denver/L=Denver/O=Enterprise Architecture/OU=Enterprise Architecture/CN=site.com/emailAddress=sample@sample.com\"", AzureNames.CertificateRoot);
        process = Process.Start(processInfo);
        process.WaitForExit();

        processInfo.Arguments = string.Format("x509 -req -sha256 -days 365 --extensions v3_ca -in {0}.csr -signkey contoso.key -out {0}.crt", AzureNames.CertificateRoot);
        process = Process.Start(processInfo);
        process.WaitForExit();

        processInfo.Arguments = string.Format("ecparam -out {0}.key -name prime256v1 -genkey", AzureNames.CertificateClient);
        process = Process.Start(processInfo);
        process.WaitForExit();

        processInfo.Arguments = string.Format("req -new -sha256 -key {0}.key -out {0}.csr -subj \"/C=US/ST=Denver/L=Denver/O=Enterprise Architecture/OU=Enterprise Architecture/CN=site.com/emailAddress=sample@sample.com\"", AzureNames.CertificateClient);
        process = Process.Start(processInfo);
        process.WaitForExit();

        processInfo.Arguments = string.Format("x509 -req -in {0}.csr -CA  {1}.crt -CAkey {1}.key -CAcreateserial -out {0}.crt -days 365 --extensions v3_ca -sha256", AzureNames.CertificateClient, AzureNames.CertificateRoot);
        process = Process.Start(processInfo);
        process.WaitForExit();
        
        process.Close();

        //combine root cert into client certificate
        var rootContents = File.ReadAllText(AzureNames.CertificatesStorageLocation + @"\" + AzureNames.CertificateRoot + ".crt");           
        File.AppendAllText(AzureNames.CertificatesStorageLocation + @"\" + AzureNames.CertificateClient + ".crt", Environment.NewLine + rootContents);

        //perform manual step
        File.Copy(AzureNames.CertificatesStorageLocation + @"\" + AzureNames.CertificateClient + ".crt", AzureNames.CertificatesStorageLocation + @"\" + AzureNames.CertificateClient + ".cer");
        var userCommand = string.Format("openssl pkcs12 –export –in {0}.cer –inkey {0}.key –out {0}.pfx -passout pass:{1}", AzureNames.CertificateClient, AzureNames.CertificatePassword);
        Console.WriteLine("Open command prompt, then run the following two statements as seperate commands(copy paste)");
        Console.WriteLine("--------------------------");
        Console.WriteLine("cd \"" + workingDirectory + "\"");
        Console.WriteLine(userCommand);
        Console.WriteLine("--------------------------");
        Console.WriteLine("After you have successfully run the commands above:");
        Console.WriteLine("       1. Close the command prompt you just opened(not this one)");
        Console.WriteLine("       2. Press any key to continue");
        Console.ReadKey();
        Console.WriteLine();
        Console.WriteLine("Continuing on...");

【问题讨论】:

  • 看起来您已经使用 SO 大约 9 年了......并且还没有“接受”任何回复。甚至你自己的解决方案 :) 谁知道 - 也许我的回应会是第一个 :) 在任何情况下,你都可以 DEFINITELY 比一堆“Process.Start()”命令做得更好;)跨度>
  • @paulsm4 我没有接受任何答案,因为没有人回答我的问题。我不能接受你的回答,因为它不能解决问题。使用 Windows 进程与问题无关,因为证书已经从名为 openSSL 的开源库正确生成。问题是如何将约束主题类型设置为 CA。您的附录可能会有所帮助,但是正在为另一台机器生成证书,因此在本地安装它并不理想。
  • 您当前的解决方案不仅笨拙 - 它不起作用。丢掉它,并替换一个有效的方法。 PowerShell 脚本和 C#/.Net 应用程序将允许您生成具有正确扩展名的自签名证书(您的原始问题),以及将其复制到您想要的任何位置(您之前没有提到的附加要求)。两者都适用于 Windows 和/或 Azure。 PS:多年来,您至少回答了一个自己的问题。但未能“接受”,留下问题“开放”。
  • @paulsm4 我能够解决这个问题。当微软推荐它时,我仍然不确定为什么你认为 openSSL 不是一个可接受的解决方案。我可以将命令移动到 bat 或 ps1 中,但我仍然需要在 C# 中启动进程时将其启动。这似乎无关紧要。

标签: c# azure ssl openssl


【解决方案1】:

你所有的 C# 代码正在做的就是生成 shell 进程来运行“x509”和朋友。

建议:由于您的环境是 MS Windows/MS Azure,请尝试以下方法:

PS PKI: New-SelfSignedCertificate

New-SelfSignedCertificate -DnsName "www.fabrikam.com", "www.contoso.com" -CertStoreLocation "cert:\LocalMachine\My"

您可以指定任意数量的扩展名(按 OID),包括:

一些常用扩展的对象标识符如下:

Application Policy. 1.3.6.1.4.1.311.21.10
Application Policy Mappings. 1.3.6.1.4.1.311.21.11
Basic Constraints. 2.5.29.19
Certificate Policies. 2.5.29.32
Enhanced Key Usage. 2.5.29.37
Name Constraints. 2.5.29.30
Policy Mappings. 2.5.29.33
Subject Alternative Name. 2.5.29.17

另见:


附录:

您也可以直接在 C# 中生成自签名证书:

https://docs.microsoft.com/en-us/dotnet/api/system.security.cryptography.x509certificates.certificaterequest?view=net-6.0

这完全支持证书扩展:

X509Extension Class

using System;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;

public class CertSelect
{
    public static void Main()
    {
        try
        {
            X509Store store = new X509Store("MY", StoreLocation.CurrentUser);
            store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);

            X509Certificate2Collection collection = (X509Certificate2Collection)store.Certificates;
            for (int i = 0; i < collection.Count; i++)
            {
                foreach (X509Extension extension in collection[i].Extensions)
                {
                    Console.WriteLine(extension.Oid.FriendlyName + "(" + extension.Oid.Value + ")");

                    if (extension.Oid.FriendlyName == "Key Usage")
                    {
                        X509KeyUsageExtension ext = (X509KeyUsageExtension)extension;
                        Console.WriteLine(ext.KeyUsages);
                    }

                    if (extension.Oid.FriendlyName == "Basic Constraints")
                    {
                        X509BasicConstraintsExtension ext = (X509BasicConstraintsExtension)extension;
                        Console.WriteLine(ext.CertificateAuthority);
                        Console.WriteLine(ext.HasPathLengthConstraint);
                        Console.WriteLine(ext.PathLengthConstraint);
                    }

                    if (extension.Oid.FriendlyName == "Subject Key Identifier")
                    {
                        X509SubjectKeyIdentifierExtension ext = (X509SubjectKeyIdentifierExtension)extension;
                        Console.WriteLine(ext.SubjectKeyIdentifier);
                    }

                    if (extension.Oid.FriendlyName == "Enhanced Key Usage")
                    {
                        X509EnhancedKeyUsageExtension ext = (X509EnhancedKeyUsageExtension)extension;
                        OidCollection oids = ext.EnhancedKeyUsages;
                        foreach (Oid oid in oids)
                        {
                            Console.WriteLine(oid.FriendlyName + "(" + oid.Value + ")");
                        }
                    }
                }
            }
            store.Close();
        }
        catch (CryptographicException)
        {
            Console.WriteLine("Information could not be written out for this certificate.");
        }
    }
}

【讨论】:

    【解决方案2】:

    现代 openSSL 使用所需的 .cnf 文件来实现原始教程中提到的功能:https://docs.microsoft.com/en-us/azure/application-gateway/self-signed-certificates

    更改第二个openSSL进程

    processInfo.Arguments = string.Format("req -config {1} -new -sha256 -key {0}.key -out {0}.csr -subj \"/C=US/ST=Denver/L=Denver/O=Enterprise Architecture/OU=Enterprise Architecture/CN=site.com/emailAddress=sample@sample.com\"", AzureNames.CertificateRoot, configFile);
    

    添加需要的configFile.cnf

    [请求]

    req_extensions = v3_req

    distinguished_name = dn

    [dn]

    [v3_req]

    基本约束 = CA:TRUE

    然后改变第三个openSSL进程

    processInfo.Arguments = string.Format("x509 -req -sha256 -days 365 -extensions v3_ca -extfile {1} -in {0}.csr -signkey contoso.key -out {0}.crt", AzureNames.CertificateRoot, configCAFile);
    

    添加所需的configFileCA.cnf

    [v3_ca]

    基本约束 = CA:TRUE

    【讨论】:

      猜你喜欢
      • 2012-08-29
      • 2018-06-11
      • 2020-07-30
      • 2021-01-09
      • 2017-03-29
      • 2012-07-20
      • 2020-06-15
      • 2012-07-19
      • 2016-07-08
      相关资源
      最近更新 更多