有没有办法使用我自己的根证书生成自签名证书(带有使用者备用名称的X509 v3)来替换MakeCert.exe

时间:2017-07-19 11:01:30

标签: powershell ssl https makecert

我遇到问题makecert无法生成具有主题备用名称(SAN)的自签名SSL证书。当通过HTTPS访问网站时,最新版本的Google Chrome会出现安全错误。我已阅读了几篇文章来尝试理解上下文,并得出结论:makecert已经足够老,并且无法支持使用SAN生成X509 v3证书。是否有其他方法可以使用可以在Windows 7及更高版本中运行的其他东西,根据该根CA生成自签名根证书和中间证书?

根证书生成如下:

makecert.exe -pe -ss Root -sr LocalMachine -n "CN=DIGITALMARKETRESEARCHAPPS PTY LTD, O=DIGITALMARKETRESEARCHAPPS PTY LTD, OU=DIGITALMARKETRESEARCHAPPS PTY LTD" -eku 1.3.6.1.5.5.7.3.1 -r -cy authority -a sha256

具有上述根CA的中间证书创建如下:

makecert.exe -pe -ss my -n "CN=www.myawesomesite.com.au, O=DIGITALMARKETRESEARCHAPPS PTY LTD, OU=DIGITALMARKETRESEARCHAPPS PTY LTD" -sky exchange -in "DIGITALMARKETRESEARCHAPPS PTY LTD"

我似乎找不到使用New-SelfsignedCertificateExNew-SelfSignedCertificate精确映射到上述参数的方法,并使用给定的根CA创建证书。

请为正确的方向提供任何帮助,我将非常感谢。

目前,我们的客户使用这个旧应用程序,它使用makecert.exe动态生成SSL证书。不幸的是,这是很久以前完成的,很难回过头来告诉他们在这一点上改变整个架构。 Google Xhrome特别抱怨makecert生成的这些证书,如下文所述:

http://news.thewindowsclub.com/deprecation-coming-to-google-chrome-heres-how-it-could-affect-your-workflow-88723/

http://www.telerik.com/blogs/understanding-fiddler-certificate-generators

1 个答案:

答案 0 :(得分:1)

即将发布的.NET Core 2.0已经添加了新的类来帮助。虽然我知道" powershell可以"或者"有一个版本的powershell做"使用.NET Core我不知道怎么做,所以这个答案可能需要一个适配器。

给定signingCert,X509Certificate2实例HasPrivateKey==true

private static X509Certificate2 CreateNewCertificate(
    X509Certificate2 signingCert,
    int newRsaKeySize,
    IEnumerable<string> sanDnsEntries)
{
    var sanBuilder = new SubjectAlternativeNameBuilder();
    string primaryDnsName = null;

    foreach (string dnsEntry in sanDnsEntries)
    {
        // Let's just use the first one as the subject.
        primaryDnsName = primaryDnsName ?? dnsEntry;

        sanBuilder.AddDnsName(dnsEntry);
    }

    // New .NET Core Create(int) method.  Or use
    // rsa = RSA.Create(), rsa.KeySize = newRsaKeySize,
    // or (on .NET Framework) new RSACng(newRsaKeySize)
    using (RSA rsa = RSA.Create(newRsaKeySize))
    {
        var certRequest = new CertificateRequest(
            $"CN={primaryDnsName}, O=Et OU=Cetera",
            rsa,
            HashAlgorithmName.SHA256,
            RSASignaturePadding.Pkcs1);

        // Explicitly not a CA.
        certRequest.CertificateExtensions.Add(
            new X509BasicConstraintsExtension(false, false, 0, false));

        certRequest.CertificateExtensions.Add(
            new X509KeyUsageExtension(
                X509KeyUsageFlags.DigitalSignature | X509KeyUsageFlags.KeyEncipherment,
                true));

        // TLS Server EKU
        certRequest.CertificateExtensions.Add(
            new X509EnhancedKeyUsageExtension(
                new OidCollection
                {
                    new Oid("1.3.6.1.5.5.7.3.1"),
                },
                false));

        // Add the SubjectAlternativeName extension
        certRequest.CertificateExtensions.Add(sanBuilder.Build());

        // Serial number.
        // It needs to be unique per issuer.
        // CA/Browser forum rules say 64 or more bits must come from a CSPRNG.
        // RFC 3280 says not to use more than 20 bytes.
        // Let's use 16 (two C# `long`s)
        byte[] serialNumber = new byte[16];

        using (RandomNumberGenerator rng = RandomNumberGenerator.Create())
        {
            rng.GetBytes(serialNumber);
        }

        // If you care about monotonicity (and believe your clock is monotonic enough):
        {
            long ticks = DateTime.UtcNow.Ticks;
            byte[] tickBytes = BitConverter.GetBytes(ticks);

            if (BitConverter.IsLittleEndian)
            {
                Array.Reverse(tickBytes);
            }

            Buffer.BlockCopy(tickBytes, 0, serialNumber, 0, tickBytes.Length);
        }

        DateTimeOffset now = DateTimeOffset.UtcNow;

        return certRequest.Create(
            signingCert,
            now,
            now.AddDays(90),
            serialNumber);
    }
}

API Documentation